delphi – TVirtualStringTree:OnMeasureItem事件和OnGetText事
发布时间:2020-12-15 09:52:08 所属栏目:大数据 来源:网络整理
导读:我有一个数组保存数据将在TVirtualStringTree上表示.该阵列是线程安全且可锁定的.并由另一个线程增长. 我的问题是,当VST执行OnMeasureItem事件来测量节点的高度时,用于测量的数据可能会在使用OnGetText事件打印数据时发生变化. 我检查了事件的执行顺序,这对
我有一个数组保存数据将在TVirtualStringTree上表示.该阵列是线程安全且可锁定的.并由另一个线程增长.
我的问题是,当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 但是我需要这样的东西才能锁定: 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; 解决方法
我会尝试通过从节点的状态中删除vsHeightMeasured并随后调用MeasureItemHeight方法来手动强制项目测量.它将再次触发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标志设置为False. if LogHasChanged then begin ThreadList.LockList; try ThreadList.Items[X].NodeMeasured := False; ThreadList.Items[X].SomeText := 'Something new'; finally ThreadList.UnlockList; end; end; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |