2012-04-15 15 views
6

Tengo una matriz contiene datos que se representarán en TVirtualStringTree. Esta matriz es segura para subprocesos y bloqueable. Y crecido por otro hilo.TVirtualStringTree: los datos cambiados entre el evento OnMeasureItem y el evento OnGetText

Mi problema es que cuando VST ejecuta el evento OnMeasureItem para medir la altura del nodo, los datos utilizados para la medición pueden cambiar cuando llega el momento de imprimir datos con el evento OnGetText.

He comprobado el orden de ejecución de los eventos y no es bueno para mi diseño. Primero, activa el evento OnMeasureItem para todos los nodos que no se inicializan y luego comienza a llamar eventos OnGetText. Es decir, supongamos que tenemos 3 nodos, los eventos serán despedidos en ese orden:

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

pero necesito algo como esto para que pueda bloquear:

OnMeasureItem for node 1 
OnGetText for node 1 

OnMeasureItem for node 2 
OnGetText for node 2 

OnMeasureItem for node 3 
OnGetText for node 3 

¿Cuál es la mejor manera de mantener la sincronización de los datos obtenidos entre los eventos OnMeasureItem y OnGetText?

No quiero bloquear mi matriz durante todos los eventos OnMeasureItem() y OnGetText().

Gracias.

Agregado 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

Agregado a la pregunta. –

+0

He borrado mi último comentario porque olvidé que estás usando 'toVariableNodeHeight'. Solo una pregunta adicional (tal vez irrelevante). ¿Qué versión de VirtualTreeView estás usando? – TLama

+0

Lo último, supongo. Salí de SVN. // Versión 5.0.0 –

Respuesta

5

me gustaría tratar de forzar la medición elemento manualmente quitando el vsHeightMeasured de los estados del nodo con la posterior llamada del método MeasureItemHeight. Activará el OnMeasureItem nuevamente. El problema es otra vez aquí, porque no debe medir el elemento más de una vez que se cambia el texto del nodo, pero todavía tiene que manejar el OnMeasureItem debido a ese material de desplazamiento.

Como mencionaste en tu comentario, puedes incluir tu propia bandera NodeMeasured en tu estructura de datos y restablecerla cuando el texto del nodo cambie (cuando cambien algunos datos en tu elemento de registro) y configurarlo después de pasar el evento OnGetText con la medición de altura del nodo forzado. Aquí es un pseudocódigo:

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; 

Y en el hilo cuando los datos se cambia, usted tiene que establecer este indicador NodeMeasured en Falso.

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

Supongo que "Excluir (Node.States, vsHeightMeasured)" es suficiente. No es necesario llamar a MeasureItemHeight(), ¿verdad? Parece que mi problema desapareció después de eliminar vsHeightMeasured. –

+0

Si solo quita el indicador 'vsHeightMeasured' del estado del nodo, el' OnMeasureItem' se debe activar para configurar el alto del nodo actual. Esto sucede siempre que el árbol está pintado, pero como dijiste, los datos (el texto) del nodo pueden cambiar entre 'OnMeasureItem' y 'OnGetText', por lo que deberías activarlo manualmente cuando tu lista de hilos esté bloqueada para ser 100 % seguro de que está midiendo la altura del mismo texto que visualiza. – TLama

Cuestiones relacionadas