- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我使用 virtualstringtree 一段时间了。我将它用于两个不同的用途,首先是一个用于选择、显示数据的普通树,其次是作为一个网格来显示 SQL 语句的输出。
我加载到树中的所有数据都来自数据库。对于树示例,我有一个 ParentId 字段来区分层次结构,对于网格示例,我只需使用 SQL 语句以及每个树的自定义记录(这是唯一的)。
我的问题涉及填充树的首选/最佳方式。我从 VST 文档中了解到,您应该将 onInitNode 事件与 rootnodecount 一起使用。然而,我发现使用 AddChild() 方法非常相似,尽管不鼓励这样做。
让我展示一些(简化的)示例:
<强>1。等级制度
type PData = ^rData;
rData = packed record
ID : Integer;
ParentID : Integer;
Text : WideString;
end;
procedure Loadtree;
var Node : PVirtualNode;
Data : PData;
begin
Q1 := TQuery.Create(Self);
try
Q1.SQL.Add('SELECT * FROM Table');
Q1.Open;
Q1.Filter := 'ParentID = -1'; //to get the root nodes
Q1.Filtered := True;
while not Q1.Eof do
begin
Node := VST.AddChild(nil);
Data := VST.GetNodeData(Node);
Data.ID := Q1.Fields[fldID].AsInteger;
Data.ParentID := Q1.Fields[fldParentID].AsInteger;
Data.Text := Q1.Fields[fldText].AsString;
//now filter the query again to get the children of this node
PopulateChildren(Data.ParentID,Node); //add children to this node and do it recursively
Q1.Next;
end;
finally
Q1.free;
end;
end;
<强>2。网格
procedure LoadGrid;
var Node : PVirtualNode;
Data : PData;
begin
Q1 := TQuery.Create(self);
try
Q1.SQL.Add('SELECT * FROM Table');
Q1.Open;
while not Q1.eof do
begin
Node := VST.AddChild(nil);
Data.ID := Q1.Fields[fldID].AsInteger;
Data.Text := Q1.Fields[fldText].AsString;
Q1.Next;
end;
finally
Q1.Free;
end;
end;
所以本质上我绕过了 RootNodeCount 和 OnInitNode 方法/属性,并使用老式的方法将节点添加到树中。看起来效果很好。请注意,在示例中我在运行时创建和销毁查询。
我开始以这种方式使用树的原因是我可以一次加载树中的所有数据,然后在使用完后释放 TQuery。我在想,无论保持 TQuery 处于事件状态/创建状态,我仍然需要使用我的 rData 记录来存储数据,因此如果我不销毁 TQuery,则会占用更多内存。目前,我的应用程序在完全加载时使用大约 250+MB,并且当我运行 SQL 报告并将其显示在 VST 中时可能会增加。当我运行包含 20000 多个节点和 50 多个列的 SQL 报告时,我发现它使用了大约 1GB 的内存。我想知道我使用 VST 的方式在最小化内存使用方面是否不正确?
创建树的生命周期查询并使用 onInitNode 事件会更好吗?这样,当树请求数据时,它会使用 onInitNode/OnInitChildren 事件从 TQuery 获取数据(即树的纯虚拟范例)?因此,我需要在表单持续时间内保持 TQuery 处于事件状态。以这种方式使用它会有任何内存优势/性能优势吗?
在上述情况下,我可以看到网格示例的差异将远小于层次结构(如果有的话) - 因为所有节点在填充时都需要初始化。
最佳答案
原因AddChild()
不鼓励的原因是它打破了组件的虚拟范例 - 您创建所有节点,即使您可能永远不需要它们。假设查询返回 100 条记录,但树当时显示 10 个节点。现在,如果用户从不向下滚动,那么您就浪费了 90 个节点的资源,因为它们永远不需要(不可见)。因此,如果您担心内存使用情况,AddChild()
是个坏主意。另一件事是,如果结果集很大,填充树需要时间,并且您的应用程序当时不会响应。当使用虚拟方式( RootNodeCount
和 OnInitNode
)时,树立即“准备好”,用户不会遇到任何延迟。
话又说回来,如果使用 AddChild()
得到(相对)小的结果集,可能是最好的选择 - 它允许您在一个简短的事务中加载数据。即,在树结构的情况下,当用户展开父节点时立即加载整个“级别”是有意义的。
将 DB 与 VT 一起使用有点棘手,因为 DB 查询也是特殊资源,有其自身的限制(您希望保持事务简短,它相对较慢,DB 可能只支持单向游标等)。
所以我想说,你必须根据具体情况来决定,具体取决于用例和数据量,即
AddChild()
一次加载全部内容或进入内部数据结构,然后通过 VT 的事件使用它;关于performance - VirtualStringTree 正确/推荐使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7624319/
是的,我知道我发布了很多问题,但那是因为我要么需要保证我做对了,我做错了什么,要么我完全一无所知,并且在文档中找不到任何东西。无论如何, 我正在尝试检查重复的节点。这是我想要的方式: 循环遍历我的节点
我有一个带有 X header 和 x 根的 virtualstringtree(启用了网格线)。 我想将子项(至少 1 个)添加到只有 1 个文本位于中间并通过所有标题(独立)的根中。因此,无论我是
我在窗体上有一个virtualstringtree控件,该控件必须显示图像列表中某些节点的图标。这很好用,但是,对于某些节点,还必须显示与节点和正方形一样高的自定义绘制图标。 我正在使用OnBefor
我想在单元格文本已完全显示时显示提示。 所以,在表单的 OnCreate 上 procedure TForm1.FormCreate(Sender: TObject); begin Virtual
是否可以隐藏 VirtualStringTree 中的特定节点?我正在实现“过滤”功能(VST 充当包含列的列表),并且我希望避免每次更改过滤器时重新加载内容 - 相反,更快的方法是告诉 VST 不要
我想每个曾经使用过Delphi的VirtualStringTree的人都会同意它是一个很棒的控件。它是一个“虚拟”控件(您的数据必须保存在其他地方),所以我在想什么数据结构最适合这样的任务? IMO认
如果 VirtualStringTree 中的节点是多行的(与 Node.States 中的 Multiline 相比),那么如何使该节点中所有列(多行列除外)的文本垂直居中? 我尝试使用OnBefo
我正在尝试更改节点的索引,因为有些特定节点始终需要位于树的底部。我试图更改 Node.Index,但这并没有改变任何东西。所以我的问题是:如何更改 PVirtualNode 的索引? 谢谢! - 杰夫
VirtualStringTree的滚动条如何刷新如果每个节点高度都更改为不同的高度。因为,滚动仍然处于相同状态,导致滚动时无法查看其他节点。 toVariableNodeHeight选项不起作用?还
我有一个带有 X 个根和 X 个子节点的 VirtualStringTree。 每个根都有一个特殊的 NodeData 分配。 每个子节点都分配了另一个 NodeData。 我怎么知道 OnFreeN
我启用了 MultiSelect 选项的 VST。 How can I retrieve the list of selected nodes in VirtualStringTree when th
我正在寻找一个程序或某些东西,如果我右键单击一个节点(或通常在 VirtualStringTree 上),它就会被触发 我有以下场景: 我的 VST 接近 ListView 。 我只能用鼠标多选根节点
是否可以锁定VirtualStringTree中的第0列(带有节点名称)像在 Excel 中一样水平滚动吗? 最佳答案 如果我没记错的话,此功能是在版本 5 中引入的。要在其 Options 中设置列
我目前在树的 OnBeforeCellPaint 事件中使用此代码: if Node.Index mod 2 = 0 then begin TargetCanvas.Brush.Color :=
我使用 virtualstringtree 一段时间了。我将它用于两个不同的用途,首先是一个用于选择、显示数据的普通树,其次是作为一个网格来显示 SQL 语句的输出。 我加载到树中的所有数据都来自数据
我有一个包含 3 列的 VST,均匀地占用可用空间。 我已在 Header.Options 中设置了 hoAutoSpring,并且 所有列都设置了 Column[x].Option 和 coAuto
所以,我的最终目标是找到一种方法,通过客户端区域内的添加/删除按钮来列出项目(例如 vsReport 中的 TListView)。 例如: |----------------| |Old Item 1
我正在尝试将项目从 D6 移动到 D-XE3。使用 VirtualStringTree 5.10 版本在 OnSaveNode 和 OnLoadEvents 中保存和加载树数据时,我遇到了垃圾。我可能
当从控件拖动到 VirtualStringTree 时,如果该控件具有 TDragObject,则预计将其用作 OnDragDrop 和 OnDragOver 中的源,但它始终返回该组件。我相信这是一
我正在严格按照本教程来保存和加载我的 VirtualStringTree:http://wiki.freepascal.org/VirtualTreeview_Example_for_Lazarus我
我是一名优秀的程序员,十分优秀!