2012-04-15 8 views
6

Ich habe ein Array enthält Daten werden auf TVirtualStringTree dargestellt werden. Dieses Array ist Thread-sicher und abschließbar. Und von einem anderen Thread gewachsen.TVirtualStringTree: Daten zwischen OnMeasureItem-Ereignis und OnGetText-Ereignis geändert

Mein Problem ist, dass, wenn VST OnMeasureItem -Ereignis ausführt, um die Höhe des Knotens zu messen, Daten für die Messung geändert werden können, wenn es zum Drucken von Daten mit OnGetText -Ereignis kommen.

Ich habe die Ausführungsreihenfolge der Ereignisse überprüft und es ist nicht gut für mein Design. Zuerst wird das OnMeasureItem-Ereignis für alle Knoten ausgelöst, das nicht initialisiert wird und dann OnGetText-Ereignisse aufruft.

OnMeasureItem for node 1 
OnMeasureItem for node 2 
OnMeasureItem for node 3 
OnGetText for node 1 
OnGetText for node 2 
OnGetText for node 3 

Aber ich brauche so etwas wie dies, damit ich sperren: Ich meine, nehmen wir an drei Knoten haben, werden Ereignisse in dieser Reihenfolge gezündet werden

OnMeasureItem for node 1 
OnGetText for node 1 

OnMeasureItem for node 2 
OnGetText for node 2 

OnMeasureItem for node 3 
OnGetText for node 3 

Was ist der beste Weg ist, um Aufrechterhaltung der Synchronisation von Daten, die zwischen OnMeasureItem- und OnGetText-Ereignissen erhalten werden?

Ich möchte nicht mein Array während aller OnMeasureItem() und OnGetText() Ereignisse sperren.

Vielen Dank.

Added ontimer:

procedure TMainForm.SyncHexLog; 
begin 
    HexLog.BeginUpdate; 
    Try 
    if (HexLog.RootNodeCount <> FirpList.ComOperationCountLagged) then 
     begin 
      HexLog.RootNodeCount := FirpList.ComOperationCountLagged; 

      // measure for fast scrolling 
      HexLog.ReInitNode(HexLog.GetLastNoInit(), True);  

      if FAutoScroll then 
      begin 
      HexLog.ScrollIntoView(HexLog.GetLast, False, False); 
      end; 
     end; 
    Finally 
    HexLog.EndUpdate; 
    End; 
end; 
+0

Zu Frage hinzugefügt. –

+0

Ich habe meinen letzten Kommentar gelöscht, da ich vergessen habe, dass Sie 'toVariableNodeHeight' verwenden. Nur eine zusätzliche (vielleicht irrelevante) Frage. Welche Version von VirtualTreeView verwenden Sie? – TLama

+0

Spätestens ich denke. Ich habe von SVN ausgecheckt. // Version 5.0.0 –

Antwort

5

Ich würde versuchen, das Element Messung manuell zu erzwingen, indem Sie die vsHeightMeasured von Knotens Staaten mit anschließendem Aufruf des MeasureItemHeight Verfahrens zu entfernen. Es wird die OnMeasureItem erneut auslösen. Das Problem ist die wieder hier, weil Sie das Element nicht mehr als einmal den Text des Knotens geändert werden sollte, aber immer noch die OnMeasureItem wegen dieser Scroll-Sachen behandeln müssen.

So wie Sie in Ihrem Kommentar erwähnt haben, können Sie Ihr eigenes NodeMeasured Flag in Ihre Datenstruktur einfügen und zurücksetzen, wenn sich der Text des Knotens ändert (wenn einige Daten in Ihrem Protokollelement geändert werden) und nach dem Übergeben setzen das Ereignis OnGetText mit der erzwungenen Knotenhöhenmessung. Hier ist ein Pseudo-Code:

procedure TForm1.VirtualStringTreeGetText(Sender: TBaseVirtualTree; 
    Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; 
    var CellText: string); 
begin 
    ThreadList.LockList; 
    try 
    // check if the own flag which indicates that the text is new, that 
    // the data has changed since the last time you were here in OnGetText 
    // is False and if so, force the node measurement to set current node 
    // height and set this flag to True to remember we already did this 
    if not ThreadList.Items[Node.Index].NodeMeasured then 
    begin 
     // fake the node measurement, remove the measured flag 
     Exclude(Node.States, vsHeightMeasured); 
     // this will trigger the OnMeasureItem again because of removed 
     // vsHeightMeasured flag from the node's state 
     VirtualStringTree.MeasureItemHeight(VirtualStringTree.Canvas, Node); 
     // set the NodeMeasured flag to remember we've measured the item 
     ThreadList.Items[Node.Index].NodeMeasured := True; 
    end; 
    // here set the node's text and unlock your thread safe list 
    CellText := ThreadList[Node.Index].SomeText; 
    finally 
    ThreadList.UnlockList; 
    end; 
end; 

Und in Ihrem Thread, wenn die Daten geändert wird, können Sie diese NodeMeasured Flag auf False zu setzen haben.

if LogHasChanged then 
begin 
    ThreadList.LockList; 
    try 
    ThreadList.Items[X].NodeMeasured := False; 
    ThreadList.Items[X].SomeText := 'Something new'; 
    finally 
    ThreadList.UnlockList; 
    end; 
end; 
+0

Ich denke, "Ausschließen (Node.States, vsHeightMeasured)" ist genug. Es ist nicht erforderlich, MeasureItemHeight() aufzurufen, oder? Es scheint, dass mein Problem nach dem Entfernen von vsHeightMeasured verschwunden ist. –

+0

Wenn Sie nur das Flag "vsHeightMeasured" aus dem Knotenstatus entfernen, muss das OnMeasureItem ausgelöst werden, um die Höhe des aktuellen Knotens festzulegen. Dies geschieht immer dann, wenn der Baum gezeichnet wird, aber wie Sie gesagt haben, können sich die Daten (der Text) des Knotens zwischen dem OnMeasureItem und dem OnGetText ändern, also sollten Sie ihn manuell auslösen, wenn Ihre Threadliste auf 100 gesetzt ist % sicher, dass Sie die Höhe für denselben Text messen, den Sie anzeigen. – TLama

Verwandte Themen