【问题标题】:How to add from a TStringList to a VirtualTreeView?如何从 TStringList 添加到 VirtualTreeView?
【发布时间】:2011-03-31 14:27:01
【问题描述】:

这是我“试图”实现的目标

我有一个生成密码的功能,然后我将其添加到 TStringList 之后,我应该用这些项目填充 VirtualTreeView,但我没有运气快速到达任何地方。应该如何以正确的方式完成?我还在学习,不是专业人士。

我的密码生成函数:

function Generate(AllowUpper,AllowLower,AllowNumbers,AllowSymbols:Boolean; PassLen:Integer):String;
const
  UpperList  = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  LowerList  = 'abcdefghijklmnopqrstuvwxyz';
  NumberList = '0123456789';
  SymbolList = '!#$%&/()=?@<>|{[]}\*~+#;:.-_';
var
  MyList  : String;
  Index   : Integer;
  i       : Integer;
begin
  Result:='';
  MyList:='';
   //here if the flag is set the elements are added to the main array (string) to process
   if AllowUpper   then MyList := MyList + UpperList;
   if AllowLower   then MyList := MyList + LowerList;
   if AllowNumbers then MyList := MyList + NumberList;
   if AllowSymbols then MyList := MyList + SymbolList;

   Randomize;
   if Length(MyList)>0 then
   for i := 1 to PassLen do
   begin
    Index := Random(Length(MyList))+1;
    Result := Result+MyList[Index];
  end;
end;

我是这样称呼它的

procedure TMain.Button3Click(Sender: TObject);
var
  i: integer;
  StrLst: TStringList;
// Timing vars...
  Freq, StartCount, StopCount: Int64;
  TimingSeconds: real;
begin
  vst1.Clear;
  Panel2.Caption := 'Generating Passwords...';
  Application.ProcessMessages;
// Start Performance Timer...
  QueryPerformanceFrequency(Freq);
  QueryPerformanceCounter(StartCount);

  StrLst := TStringList.Create;
  try
  for i := 1 to PassLenEd.Value do
   StrLst.Add(Generate(ChkGrpCharSelect.Checked[0],ChkGrpCharSelect.Checked[1],
    ChkGrpCharSelect.Checked[2],ChkGrpCharSelect.Checked[3],20));
// Stop Performance Timer...
    QueryPerformanceCounter(StopCount);
    TimingSeconds := (StopCount - StartCount) / Freq;
// Display Timing... How long it took to generate
    Panel2.Caption := 'Generated '+IntToStr(PassLenEd.Value)+' passwords in '+
    FloatToStrF(TimingSeconds,ffnumber,1,3)+' seconds';

// Add to VirtualTreeList - here???
finally
    StrLst.Free;
  end;
end;

我希望我这样做完全错误,我已经尝试了 2 天,如果有人能直接告诉我应该如何去做,那就太好了。

克里斯

【问题讨论】:

  • 为什么选择虚拟树列表?这是一个非常复杂的控件?为什么不使用列表视图或其他同样简单的方法?
  • 我最初只使用标准的 TListView 和 TAdvListView,但是当添加大量数据时它变得太多,即使使用 BeginUpdate 和 EndUpdate。我正在测试另一个可以在不到 12 秒内生成超过一百万个密码的程序的生成 - 我听说 VirtualTreeView 非常适合这样的事情,我正在努力学习它。
  • @David,您应该发布您的最后一条评论作为答案。两秒钟的代码,它将解决 OP 的问题。
  • @Shamballa 不是您的问题,但如果性能是您的目标,那么在您的日常工作中进行一些简单的更改,我设法在不到一秒的时间内生成了 1,000,000 个密码(不显示)。使用您的确切例程,我的机器大约需要 2.2 秒才能生成相同的 1,000,000 个密码。
  • @Shamballa,其他的......看起来你使用面板来显示消息......为什么不使用标签?

标签: delphi virtualtreeview


【解决方案1】:

我可能会坚持使用 TListView,但将其转换为虚拟列表视图。像这样:

procedure TMyForm.FormCreate;
begin
  ListView.OwnerData := True;
  ListView.OnData = ListViewData;
  ListView.Items.Count := StringList.Count;
end;

procedure TMyForm.ListViewData(Sender: TObject; ListItem: TListItem);
begin
  ListItem.Caption := StringList[ListItem.Index];
end;

您可以立即将数百万件物品放入其中。

【讨论】:

  • 非常感谢您,我现在将尝试您对 TListView 的建议。我仍然想知道我应该如何处理 VirtualTreeList 的数据,我已经阅读了很多关于这里的问题的帖子,似乎我会使用 OnGetText?很抱歉继续讨论 VirtualTreeList 只是我真的很想知道如何使用它 - 只是一个问题,但如果我要使用它,是否也会使用 TStringList 方式,还是需要完全不同的方式?跨度>
  • 使用虚拟控件,您可以将数据存储在某个单独的容器中,并在控件想要检索要显示的数据时响应控件发送的事件。您可以使用您使用的任何虚拟控件将数据保存在字符串列表中。
【解决方案2】:

您最好将您的字符串列表存储在代码中的其他位置以“虚拟”使用它,例如在表格的私人部分。填充后,只需设置:

vst1.Clear;
vst1.RootNodeCount := StrLst.Count;

在树的获取文本事件上:

procedure TForm1.vst1GetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex;
  TextType: TVSTTextType; var CellText: string);
begin
  CellText := StrLst[Node.Index];
end;

【讨论】:

  • +1,它更容易但可能比我的版本慢一点:)
  • 它会更快,因为在我的版本中我不需要将所有孩子都添加到树中。 Virtual Treeview 一开始只会创建可见节点。
  • @Linas 谢谢 - 这是在理解 OnGetText 时遇到的主要问题,我试图从 TStringList 加载,但它们都被连接成一个大字符串!
  • 与 TListView 版本基本相同。不错!
  • @Shaballa 不需要每次都释放它。您可以在生成所有项目之前清除字符串列表。
【解决方案3】:

或者如果你真的想要 VirtualTreeView,你可以使用这样的东西...... 我不确定这是否是绝对明确的解决方案,我熟悉记录,而不仅仅是一个变量。

procedure TMain.Button3Click(Sender: TObject);
var i: integer;
    p: PString;
    Freq, StartCount, StopCount: Int64;
    TimingSeconds: real;

begin
  Panel2.Caption := 'Generating Passwords...';
  Application.ProcessMessages;

  QueryPerformanceFrequency(Freq);
  QueryPerformanceCounter(StartCount);

  vst1.BeginUpdate;
  vst1.Clear;

  for i := 1 to PassLenEd.Value do
    begin
      p := VirtualStringTree1.GetNodeData(VirtualStringTree1.AddChild(nil));
      p^ := Generate(ChkGrpCharSelect.Checked[0],ChkGrpCharSelect.Checked[1], ChkGrpCharSelect.Checked[2],ChkGrpCharSelect.Checked[3],20);
    end;

  vst1.EndUpdate;

  QueryPerformanceCounter(StopCount);
  TimingSeconds := (StopCount - StartCount) / Freq;
  Panel2.Caption := 'Generated '+IntToStr(PassLenEd.Value)+' passwords in '+
  FloatToStrF(TimingSeconds,ffnumber,1,3)+' seconds';
end;

您需要实现 OnGetNodeDataSize 和 OnGetText 事件来初始化节点数据大小并显示文本。

procedure TMain.vst1GetNodeDataSize(
  Sender: TBaseVirtualTree; var NodeDataSize: Integer);
begin
  NodeDataSize := SizeOf(string);
end;

procedure TMain.vst1GetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: string);
begin
  CellText := PString(VirtualStringTree1.GetNodeData(Node))^;
end;

编辑 1:我已更正数据类型 UnicodeString -> String

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 2012-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-05
    • 1970-01-01
    相关资源
    最近更新 更多