9

速度に大きな違いがあるため、Listview ではなく VirtualStringTree を使用してプロジェクトをビルドしようとしています。問題は、デモを調べた後でも、それを ListView として使用する方法を正確に理解できないことです。同様に、追加、削除、および基本的に ListView 項目の操作は非常に簡単ですが、VT を見ると、ほとんど複雑すぎます。

私が探しているのは、サブアイテムなどを備えた ListView のような VT だけです。

VT で使用したい ListView を使用するいくつかのルーチンを次に示します (これは単なる疑似例です。

procedure Add;
begin
  with ListView.Items.Add do
    Begin
      Caption := EditCaption.Text;
      SubItems.Add(EditSubItem.Text):
    End;

end;

Procedure ReadItem(I : Integer);
begin

   ShowMessage(ListView.Items[I].Caption);
   ShowMessage(ListView.Items[I].SubItems[0]);

end;

もちろん、削除機能もありますが、それは1行のようなものなので、私は気にしませんでした:P

上記の例を ListView スタイルの VT を使用するように変換できる人はいますか?

ありがとう!

4

5 に答える 5

11

仮想モードでリスト ビューを使用しないのはなぜですか。それは見た目と感触が正しく、優れたパフォーマンスを発揮します。

Delphi TListView コントロールは、Windows リスト ビュー コンポーネントのラッパーです。デフォルトの操作モードでは、リスト データのコピーがアプリから Windows コントロールに転送されますが、これは低速です。

これに代わるものは、Windows 用語では仮想リスト ビューとして知られています。アプリはデータを Windows コントロールに渡しません。代わりに、コントロールがデータを表示する必要がある場合、必要なデータのみをアプリに要求します。

Delphi TListView コントロールは、OwnerData プロパティを使用して仮想リスト ビューを公開します。リスト ビューのコードを多少書き直す必要がありますが、それほど難しくありません。

また、同様の根拠をカバーする別の質問へのリンクも提供します。奇妙なことに、その質問に対する受け入れられた回答は、質問がリスト ビュー コントロールに関するものであったにもかかわらず、リスト ボックスについて述べていました。

于 2011-01-03T17:53:18.420 に答える
6

VirtualStringTree では、単純な TListView よりも少し複雑ですが、VirtualStringTree の使用方法について少し前に作成した非常に単純なチュートリアルを次に示しますhttp://www.youtube.com/watch?v=o6FpUJhEeoY助けて、乾杯!

于 2011-01-03T18:34:39.057 に答える
5

通常の TListView を使用するだけですが、仮想モードで使用してください。

それは本当に簡単です:

  1. OwnerDataプロパティを次のように設定しますtrue
  2. OnDataイベント ハンドラーを実装します。

3 行の単純なリストを表示するサンプル実装:

Type TMyItem=record
  Item:String;
  SubItem:String;
end;

var Items:Array of TMyItem;

// set up some in-memory dataset.. choose your own layout
SetLength(Items,3);
Items[0].Item := 'foo1';
Items[0].SubItem := 'bar1';

Items[1].Item := 'foo2';
Items[1].SubItem := 'bar2';

Items[2].Item := 'foo3';
Items[2].SubItem := 'bar3';

// tell ListView1 how many items there are
ListView1.Items.Count := Length(Items); 

procedure TfrmMain.ListView1Data(Sender: TObject; Item: TListItem);
begin
  Item.Caption := IntToStr(Item.Index);
  Item.SubItems.Add( MyArray[Item.Index] );
  Item.SubItems.Add( UpperCase(MyArray[Item.Index]) );
end;

// Updating a value:
Items[1].Item := 'bzzz';
ListView1.Update;

それで全部です!

注意事項:

  1. もう ListView1.Items.Add() を呼び出す必要はありません。
  2. データの独自のリストをメモリのどこかに保持するか、リアルタイムでデータを作成する必要があるため、リストビューにデータを「保存」することはできなくなります。
  3. items.count プロパティを設定する必要があります。そうしないと、何も表示されません。
  4. 何かが変更された場合は、ListView1.Update() を呼び出します。
于 2011-01-04T02:06:07.527 に答える
4
procedure Add;
Var
  Data: PLogData;
  XNode: PVirtualNode;
begin
  with vst do
    Begin
      XNode := AddChild(nil);
      ValidateNode(XNode, False);
      Data := GetNodeData(Xnode); 
      Data^.Name:= EditCaption.Text;
      Data^.Msg := EditSubItem.Text;
    End;

end;

Procedure ReadItem(I : Integer);
var
  Data: PLogData;
begin
  if not Assigned(vst.FocusedNode) then Exit;

  Data := vst.GetNodeData(vst.FocusedNode);
  ShowMessage(Data^.Name);
  ShowMessage(Data^.Msg);

end;

基本的にそれはあなたがする必要があることですが、VirtualStringTree はそれを完全に理解するために一緒に働く他の多くのものを持っています/必要とします。一度「理解」すれば、VST は簡単でパワフルです。次のウェブページが役に立ちます: http://wiki.freepascal.org/VirtualTreeview_Example_for_Lazarus

以下に、単純な VST ログ表示に使用するコードを追加します。すべてのコードを datamodule に保持します。プロシージャ Log を使用して情報を表示し、FormMain.vstLog を自分のものに変更するだけです...

unit udmVstLog;

interface

uses
  SysUtils, Windows, Forms, Classes, Graphics,
  VirtualTrees, ActnList, Dialogs, ExtDlgs;

type
  PLogData = ^TLogData;
  TLogData = record
    IsErr   : Boolean;
    Name: String;
    Msg : String;
  end;

type
  TdmVstLog = class(TDataModule)
    actlst1: TActionList;
    actClear: TAction;
    actSave: TAction;
    actCopyLine2Mem: TAction;
    sdlgLog: TSaveTextFileDialog;
    procedure DataModuleCreate(Sender: TObject);
    procedure actClearExecute(Sender: TObject);
    procedure actSaveExecute(Sender: TObject);
    procedure actCopyLine2MemExecute(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure VSTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
    procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
    procedure VSTPaintText(Sender: TBaseVirtualTree;
      const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
      TextType: TVSTTextType);
  end;

  procedure Log(aIsErr: Boolean; AName, AMsg: string); overload;
  procedure Log(AName, AMsg: string); overload;
  procedure Log(AMsg: string); overload;

var
  dmVstLog: TdmVstLog;

implementation

uses uFormMain, ClipBrd;

{$R *.dfm}
procedure Log(aIsErr: Boolean; AName, AMsg: string);
Var
  Data: PLogData;
  XNode: PVirtualNode;
begin
  XNode:=FormMain.vstLog.AddChild(nil);
  FormMain.vstLog.ValidateNode(XNode, False);
  Data := FormMain.vstLog.GetNodeData(Xnode);
  Data^.IsErr := aIsErr;
  if aIsErr then
    Data^.Name:= DateTimeToStr(Now) + ' ERROR ' + AName
  else
    Data^.Name:= DateTimeToStr(Now) + ' INFO ' + AName;
  Data^.Msg:= AMsg;
end;

procedure Log(AName, AMsg: string);
begin
  Log(False,AName,AMsg);
end;

procedure Log(AMsg: string);
begin
  Log(False,'',AMsg);
end;



// VirtualStringTree Events defined here
procedure TdmVstLog.VSTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
  Data: PLogData;
begin
  Data:=Sender.GetNodeData(Node);
  Finalize(Data^);
end;

procedure TdmVstLog.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
 Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
var
  Data: PLogData;
begin
  Data := Sender.GetNodeData(Node);
  case Column of
    0: CellText := Data^.Name + ' - '+ Data^.Msg;
  end;
end;

procedure TdmVstLog.VSTPaintText(Sender: TBaseVirtualTree;
  const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  TextType: TVSTTextType);
Var
  Data: PLogData;
begin
  Data := Sender.GetNodeData(Node);

  if Data^.IsErr then
    TargetCanvas.Font.Color:=clRed;

end;

//PopUpMenu Actions defined here!
procedure TdmVstLog.actClearExecute(Sender: TObject);
begin
  FormMain.vstLog.Clear;
end;

procedure TdmVstLog.actCopyLine2MemExecute(Sender: TObject);
var
  Data: PLogData;
begin
  if not Assigned(FormMain.vstLog.FocusedNode) then Exit;

  Data := FormMain.vstLog.GetNodeData(FormMain.vstLog.FocusedNode);
  ClipBoard.AsText := Data^.Name + ' - ' + Data^.Msg;
end;

procedure TdmVstLog.actSaveExecute(Sender: TObject);
Var
  XNode: PVirtualNode;
  Data: PLogData;
  ts: TStringList;
begin
  If FormMain.vstLog.GetFirst = nil then Exit;
  XNode:=nil;
  if sdlgLog.Execute then begin
    ts:= TStringList.create;
    try
      Repeat
        if XNode = nil then XNode:=FormMain.vstLog.GetFirst Else XNode:=FormMain.vstLog.GetNext(XNode);
        Data:=FormMain.vstLog.GetNodeData(XNode);
        ts.Add(Data^.Name + ' - '+ Data^.Msg);
      Until XNode = FormMain.vstLog.GetLast();
      ts.SaveToFile(sdlgLog.FileName);
    finally
      ts.Free;
    end;
  end;

end;

// Datamodule Events defined here
procedure TdmVstLog.DataModuleCreate(Sender: TObject);
begin
  with FormMain.vstLog do begin
    NodeDataSize := SizeOf(TLogData);
    OnFreeNode := VSTFreeNode;
    OnGetText := VSTGetText;
    OnPaintText := VSTPaintText;
  end;
end;

end.

...

procedure RemoveSelectedNodes(vst:TVirtualStringTree);
begin
  if vst.SelectedCount = 0 then Exit;
  vst.BeginUpdate;
  vst.DeleteSelectedNodes;
  vst.EndUpdate;
end;

procedure RemoveAllNodes(vst:TVirtualStringTree);
begin
  vst.BeginUpdate;
  vst.Clear;
  vst.EndUpdate;
end;
于 2011-01-03T20:46:26.787 に答える
1

VT Contributionsパックを入手して、仮想文字列ツリーの子孫のいくつかをチェックしてください。それはそこにあります。プロジェクトで使用したことはありませんが、Virtual String Tree を使いやすくしているようです。


それにもかかわらず、ここに私の入門書があります:

Virtual String Tree をかなり使用した後、それを最大限に活用できる唯一の方法は、init ノード/子関数を実装し、ルート ノード数を設定することであることがわかりました。 := 真。

VirtualStringTree を使用するのは非常に簡単です。get text 関数とノード サイズ関数を実装するだけです (ツリーの背後にあるデータとして使用するレコードのサイズに等しく設定します)。

ほとんどの場合、簡単に実行できることがわかりました TVirtualTreeNodeRecordData = record Data : TVirtualTreeNodeData; end

init 関数でデータ オブジェクトを作成します。ポインターは自動的に作成されますが、オブジェクトを解放する必要があります (再度、別の削除ノード コールバックを使用します)。

于 2011-01-03T20:51:35.367 に答える