2012-04-15 33 views
6

Tôi có một mảng giữ dữ liệu sẽ được trình bày trên TVirtualStringTree. Mảng này an toàn và có thể khóa. Và được trồng bởi một sợi khác.TVirtualStringTree: Dữ liệu thay đổi giữa sự kiện OnMeasureItem và sự kiện OnGetText

Vấn đề của tôi là, khi VST thực hiện sự kiện OnMeasureItem để đo chiều cao của nút, dữ liệu được sử dụng để đo có thể thay đổi khi nó đến điểm in dữ liệu với sự kiện OnGetText.

Tôi đã kiểm tra thứ tự thực hiện các sự kiện và nó không tốt cho thiết kế của tôi. Đầu tiên Nó kích hoạt sự kiện OnMeasureItem cho tất cả các nút không được khởi tạo sau đó nó bắt đầu gọi các sự kiện OnGetText. Ý tôi là, giả sử chúng ta có 3 nút, sự kiện sẽ được bắn theo thứ tự:

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

Nhưng tôi cần một cái gì đó như thế này để tôi có thể khóa:

OnMeasureItem for node 1 
OnGetText for node 1 

OnMeasureItem for node 2 
OnGetText for node 2 

OnMeasureItem for node 3 
OnGetText for node 3 

cách tốt nhất để là gì duy trì đồng bộ dữ liệu thu được giữa các sự kiện OnMeasureItem và OnGetText?

Tôi không muốn khóa mảng của mình trong tất cả các sự kiện OnMeasureItem() và OnGetText().

Cảm ơn bạn.

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

Đã thêm vào câu hỏi. –

+0

Tôi đã xóa nhận xét cuối cùng của mình vì tôi quên bạn đang sử dụng 'toVariableNodeHeight'. Chỉ một câu hỏi bổ sung (có thể không liên quan). Bạn đang sử dụng phiên bản VirtualTreeView nào? – TLama

+0

Mới nhất tôi đoán. Tôi đã kiểm tra từ SVN. // Phiên bản 5.0.0 –

Trả lời

5

tôi sẽ cố gắng để buộc các đo lường mục bằng tay bằng cách loại bỏ các vsHeightMeasured từ các tiểu bang nút của với các cuộc gọi tiếp theo của phương pháp MeasureItemHeight. Nó sẽ kích hoạt lại OnMeasureItem. Vấn đề là một lần nữa ở đây, bởi vì bạn không nên đo lường mục nhiều hơn một lần văn bản của nút được thay đổi, nhưng vẫn phải xử lý OnMeasureItem vì công cụ cuộn đó.

Vì vậy, như bạn đã đề cập trong bình luận, bạn có thể bao gồm cờ NodeMeasured của riêng bạn vào cấu trúc dữ liệu của bạn và đặt lại nó khi văn bản của nút sẽ thay đổi (khi một số dữ liệu trong mục nhật ký của bạn thay đổi) và đặt nó sau khi bạn vượt qua sự kiện OnGetText với đo chiều cao nút bắt buộc. Đây là một giả:

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; 

Và trong chủ đề của bạn khi dữ liệu bị thay đổi, bạn phải thiết lập NodeMeasured cờ này là False.

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

Tôi đoán "Loại trừ (Node.States, vsHeightMeasured)" là đủ. Không cần phải gọi MeasureItemHeight(), phải không? Dường như vấn đề của tôi biến mất sau khi gỡ bỏ vsHeightMeasured. –

+0

Nếu bạn chỉ xóa cờ 'vsHeightMeasured' khỏi trạng thái nút,' OnMeasureItem' phải được kích hoạt để thiết lập chiều cao của nút hiện tại. Điều này xảy ra bất cứ khi nào cây được vẽ mặc dù, nhưng như bạn đã nói dữ liệu (văn bản) của nút có thể thay đổi ở giữa 'OnMeasureItem' và' OnGetText', vì vậy bạn nên kích hoạt nó theo cách thủ công khi danh sách chủ đề của bạn bị khóa là 100 % chắc chắn bạn đang đo chiều cao cho cùng một văn bản bạn hiển thị. – TLama

Các vấn đề liên quan