【问题标题】:GetText from TVirtualStringTree is getting triggered more times来自 TVirtualStringTree 的 GetText 被触发更多次
【发布时间】:2016-07-30 15:12:53
【问题描述】:

请看下面的代码:

unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, VirtualTrees, Vcl.StdCtrls;

type
  TTreeData = record
    Fields: array of String;
  end;
  PTreeData = ^TTreeData;

const
  szVirtualTree = SizeOf(TTreeData);

type
  TForm2 = class(TForm)
    tree: TVirtualStringTree;
    Button1: TButton;
    procedure treeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
    procedure treeGetNodeDataSize(Sender: TBaseVirtualTree;
      var NodeDataSize: Integer);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
var
  LTreeData: PTreeData;
  Node: PVirtualNode;
  cols, rows, col, row: Integer;
begin
  cols:= 2;
  rows:= 2;

  Tree.Header.Columns.Clear;
  if cols > 0 then
    for col := 0 to cols - 1 do
      with Tree.Header.Columns.Add do
        begin
          Text:= 'H' + IntToStr(col);
          Width:= 80;
        end;

  Tree.Clear;
  Tree.BeginUpdate;

  if (cols> 0) and (rows > 0) then
    for row := 0 to rows - 1 do
      begin
        Node:= Tree.AddChild(nil,nil);
        Tree.ValidateNode(Node,False);

        LTreeData:= Tree.GetNodeData(Node);
        SetLength(LTreeData^.Fields, cols);

        if cols > 0 then
          for col := 0 to cols - 1 do
            LTreeData^.Fields[col]:= '[' + inttostr(col) + ',' + inttostr(row) + ']';
      end;

  Tree.EndUpdate;
end;

procedure TForm2.treeGetNodeDataSize(Sender: TBaseVirtualTree;
  var NodeDataSize: Integer);
begin
  NodeDataSize:= szVirtualTree;
end;

procedure TForm2.treeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var
  LTreeData: PTreeData;
begin
  LTreeData:= Sender.GetNodeData(Node);
  CellText:= LTreeData^.Fields[Column];
  showmessage(CellText);
end;

end.

按下按钮后,我得到的消息是:

[0,0] 
[0,0] 
[0,0] 
[0,0] 
[1,0]
[1,0]
[1,0]
[1,0] 
[0,1]
[0,1]
[0,1]
[0,1] 
[1,1]
[1,1]
[1,1]
[1,1]

基本上GetText对于每个节点和每列被触发4次。

为什么不是只触发一次?像这样:[0,0] [1,0] [0,1] [1,1]

【问题讨论】:

  • 这是设计使然。注意参数。您的事件处理程序会针对不同的列和文本类型分别触发。
  • 您确实需要获得比ShowMessage 更好的日志记录。致电AllocConsole 并使用WriteLn。或者一个简单的OutputDebugString
  • 直到现在我才使用这个工具大卫!
  • 原因可能是arrayszVirtualTree造成的吗?
  • 我不太了解 VST,但很自然地,作为 虚拟,它调用 OnGetText 来获取文本节点。

标签: delphi virtualtreeview tvirtualstringtree


【解决方案1】:

控件使用所谓的虚拟范例。作者 Mike Lischkeexplains this like so

正如名称已经表明的那样,此控件使用与其他此类控件不同的树管理范例。它对它管理的数据一无所知(除了它的大小),甚至不知道一个节点的标题。一切都通过事件(或通过覆盖的方法的后代)从应用程序中检索。

控件不跟踪节点标题。每当它需要知道它们时,它就会触发OnGetText 方法。该控件不缓存,不记住节点标题。因此,如果控制代码的多个部分依赖于标题,那么同一节点的事件将被多次调用。

您观察到的行为是完全正常的,完全可以预料。 OnGetText 处理程序的工作是产生节点的文本。如果同一个问题被问了两次,请不要担心。只要确保您每次都给出相同的答案!

【讨论】:

  • 回答得好!谢谢大卫!
猜你喜欢
  • 1970-01-01
  • 2013-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多