2012-04-15 1 views
6

배열 보유 데이터가 TVirtualStringTree에 표시됩니다. 이 배열은 스레드로부터 안전하고 잠글 수 있습니다. 그리고 다른 스레드에 의해 성장했다.TVirtualStringTree : OnMeasureItem 이벤트와 OnGetText 이벤트간에 데이터가 변경되었습니다.

내 문제는 VST가 노드의 높이를 측정하기 위해 OnMeasureItem 이벤트를 실행할 때 OnGetText 이벤트로 데이터를 인쇄 할 때 측정에 사용 된 데이터가 변경 될 수 있다는 점입니다.

이벤트의 실행 순서를 확인했는데 내 디자인에 좋지 않습니다. 먼저 초기화되지 않은 모든 노드에 대해 OnMeasureItem 이벤트를 발생시킨 다음 OnGetText 이벤트를 호출하기 시작합니다.

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

하지만 잠글 수 있도록이 같은 뭔가가 필요 : 내 말은 , 우리는 3 개 노드가 가정, 이벤트가 순서대로 발사됩니다

OnMeasureItem for node 1 
OnGetText for node 1 

OnMeasureItem for node 2 
OnGetText for node 2 

OnMeasureItem for node 3 
OnGetText for node 3 

하는 가장 좋은 방법은 무엇입니까 OnMeasureItem과 OnGetText 이벤트 사이에서 얻은 데이터의 동기화를 유지합니까?

모든 OnMeasureItem() 및 OnGetText() 이벤트 중에 배열을 잠글 싶지 않습니다.

감사합니다.

추가 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

질문에 추가되었습니다. –

+0

당신이'toVariableNodeHeight'를 사용하고 있다는 것을 잊어 버렸기 때문에 마지막 코멘트를 삭제했습니다. 단 하나의 추가 질문 (무관 한 질문 일 수도 있음). 사용중인 VirtualTreeView의 버전은 무엇입니까? – TLama

+0

추측 컨데. 나는 SVN에서 체크 아웃했다. // Version 5.0.0 –

답변

5

나는 MeasureItemHeight 방법의 후속 호출에 노드의 상태에서 vsHeightMeasured을 제거하여 수동으로 항목 측정을 강제로 시도 할 것입니다. 다시 OnMeasureItem을 트리거합니다. 문제는 입니다. 다시입니다. 노드의 텍스트가 두 번 이상 변경되면 항목을 측정하지 않아야하지만 스크롤하는 내용으로 인해 OnMeasureItem을 처리해야하므로 문제가됩니다.

의견에서 언급 한대로 데이터 구조에 자신의 NodeMeasured 플래그를 포함시키고 로그 항목의 일부 데이터가 변경 될 때 노드의 텍스트가 변경되면 재설정하여 전달한 후 설정하십시오 강제 노드 높이 측정과 함께 OnGetText 이벤트. 여기에 의사 코드는 다음과 같습니다

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; 

그리고 데이터가 변경됩니다 스레드에서

, 당신은 거짓이 NodeMeasured 플래그를 설정해야합니다.

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

"Exclude (Node.States, vsHeightMeasured)"이면 충분합니다. MeasureItemHeight()를 호출 할 필요는 없습니다. 그렇습니까? vsHeightMeasured를 제거한 후 내 문제가 사라진 것 같습니다. –

+0

노드 상태에서'vsHeightMeasured' 플래그 만 제거하면 현재 노드의 높이를 설정하기 위해'OnMeasureItem'을 실행해야합니다. 이것은 트리가 칠해질 때마다 발생하지만 노드의 데이터 (텍스트)가 OnMeasureItem과 OnGetText 사이에서 변경 될 수 있으므로 스레드 목록이 100으로 잠겨있을 때 수동으로 트리거해야합니다 당신이 표시하는 텍스트의 높이를 측정하고 있는지 확인하십시오. – TLama

관련 문제