首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >TVirtualStringTree:在OnMeasureItem事件和OnGetText事件之间更改的数据

TVirtualStringTree:在OnMeasureItem事件和OnGetText事件之间更改的数据
EN

Stack Overflow用户
提问于 2012-04-15 15:53:46
回答 1查看 1.2K关注 0票数 7

我有一个保存数据的数组,这些数据将在TVirtualStringTree上表示。这个数组是线程安全的,并且是可锁的。并由另一个线程生长。

我的问题是,当VST执行OnMeasureItem事件来测量节点的高度时,当使用OnGetText事件打印数据时,用于测量的数据可能会发生变化。

我已经检查了事件的执行顺序,这对我的设计不好。首先,它为所有未初始化的节点触发OnMeasureItem事件,然后开始调用OnGetText事件。我的意思是,假设我们有3个节点,事件将按此顺序触发:

代码语言:javascript
复制
OnMeasureItem for node 1
OnMeasureItem for node 2
OnMeasureItem for node 3
OnGetText for node 1
OnGetText for node 2
OnGetText for node 3

但我需要这样的东西,这样我才能锁定:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-04-15 18:16:10

我会尝试通过随后调用MeasureItemHeight方法从节点的状态中删除vsHeightMeasured来手动强制项目测量。它将再次触发OnMeasureItem。这里的问题再次出现,因为您不应该测量项目超过一次节点的文本更改,但仍然必须处理OnMeasureItem,因为滚动的东西。

因此,正如您在注释中提到的,您可以将自己的NodeMeasured标志包含到数据结构中,并在节点的文本发生更改时(当日志项中的某些数据发生更改时)重置它,并在您传递带有强制节点高度测量的OnGetText事件后设置它。下面是一个伪代码:

代码语言:javascript
复制
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;

代码语言:javascript
复制
if LogHasChanged then
begin
  ThreadList.LockList;
  try
    ThreadList.Items[X].NodeMeasured := False;
    ThreadList.Items[X].SomeText := 'Something new';
  finally
    ThreadList.UnlockList;
  end;
end;
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10160396

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档