【问题标题】:TVirtualStringTree and vertical Scroll is not working properlyTVirtualStringTree 和垂直滚动无法正常工作
【发布时间】:2012-04-06 13:37:52
【问题描述】:

我已经学会了如何使用 TVirtualStringTree,我发现它非常棒。我有一个名为 PackedList 的自定义非可视列表,它由另一个线程填充。我想实时显示 TVirtualStringTree 中的所有列表内容。所以我在主窗体上放了一个计时器,每 500 毫秒更新一次 HexLog(即 TVirtualStringTree)的 RootNodeCount。

我所有的数据都出现在 VirtualStringTree 上,而且我没有任何速度问题,非常好。但是垂直滚动条存在一个问题。当我在控件上按 Ctrl+End 以跳转到列表的末尾时,它会转到中间的某个位置。同样,当我将滚动条拖到最后时,它不会走到最后。但是 HexLog 知道 DataCount。为什么不跳到最后?如果我按几次 Ctrl+END 就会到达终点。

在定时器例程中,我想说HexLog通过代码跳转到列表的末尾。我该怎么做以及如何正确处理垂直滚动条?

procedure TMainForm.StatusUpdateTimerTimer(Sender: TObject);
begin
   if (FirpList.ComOperationCount > 0) and (PacketList.Items.Count <> FirpList.ComOperationCount) then
    begin
      HexLog.RootNodeCount := PacketList.Items.Count;
    end;
end;

procedure TMainForm.HexLogMeasureItem(Sender: TBaseVirtualTree;
  TargetCanvas: TCanvas; Node: PVirtualNode; var NodeHeight: Integer);
begin
  if Sender.MultiLine[Node] then
  begin
    TargetCanvas.Font := Sender.Font;
    NodeHeight := HexLog.ComputeNodeHeight(TargetCanvas, Node, 1, FirpList.ComOperations[Node^.Parent^.Index].DataAsHexString(FAppSettings.HexLogColumnCharWidth) + #13#10);
  end;
end;

TLama 建议的回复不能正常工作,请看图片解释:

详细图片说明见该链接:http://i43.tinypic.com/1445thi.png

【问题讨论】:

    标签: delphi scroll virtualtreeview tvirtualstringtree


    【解决方案1】:

    要跳转到树的末尾,请调用ScrollIntoView(GetLast)

    要滚动到特定节点,控件需要将所有先前节点的高度相加,以便确定正确的偏移量。

    您的节点有不同的高度。如果您没有在某处初始化节点的实际高度,则控件将 DefaultNodeHeight 属性用于任何未初始化的节点。看起来该高度比树中的任何实际节点高度都短,因此控件最终计算出一个小于预期的偏移量,并滚动到那里而不是您想要的位置。

    确保您正在处理OnMeasureItem 事件,并且您在Options.MiscOptions 中设置了toVariableNodeHeight 选项。如果你不这样做,那么控件将只为每个节点使用当前分配的高度,并为任何未初始化的节点使用默认高度。

    如果您手动分配NodeHeight 而不是设置toVariableNodeHeight 并处理OnMeasureItem,您可以获得您在此处报告的行为。

    【讨论】:

    • 嗨 Rob,我在 MeasureItem 上有处理程序来计算 MultiLine 子高度。未在 MiscOptions 上设置 toVariableNodeHeight。我做到了,现在 ScrollIntoView() 正确地跳到了结尾。但它稍微向下滚动,大约需要 2 秒才能到达结尾,这是不可接受的:/
    • 除了计算所有新节点的高度之外,计算最后一个节点的偏移量需要时间的主要事情是节点位置缓存是否无效。在GetDisplayRect 中设置断点,查看调用ScrollIntoView 时是否处于tsUseCache 状态。当缓存有效时,树可以更快地找到节点的位置,但是改变节点的数量会使缓存失效。工作线程需要时间来重新验证它。
    • (tsUseCache in FStates) 当我调用 ScrollIntoView() 时,GetDisplayRect() 函数中的条件返回 false。我现在该怎么办?对于这个项目,我使用的是 RichEdit 控件,因为遇到速度问题,我将所有设计更改为使用 VirtualStringTree。现在我又在同一点:/实际上我很难理解为什么我需要计算整个消息的高度才能跳到列表的末尾。我只想在数据事务处于活动状态时每 500 毫秒向用户显示最后一条消息。
    • 您需要所有节点的高度,因为控件需要知道要显示的偏移量。如果它不知道它的偏移量,那么它就无法正确显示滚动条或正确向上滚动。使用分析器找出滚动操作的哪些部分花费的时间最多,然后看看您是否可以减少在这些部分花费的时间。
    • 我这样做了。如果没有 OnMeasureItem 处理程序,ScrollIntoView() 需要 720 毫秒。使用上面显示的 OnMeasureItem 处理程序需要 1799 毫秒。有没有办法强制 VirtualStringTree 在不滚动的情况下计算节点高度,以便所有节点的状态都有 tsUseCache?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多