Переключение с ListView на VirtualStringTree
Я пытаюсь построить свои проекты с VirtualStringTree, а не Listview, из-за огромной разницы в скорости. Дело в том, что даже после просмотра демо, я просто не могу понять, как именно я буду использовать его в качестве ListView. Например, добавление, удаление и в основном просто работа с элементами ListView так легко, но когда я смотрю на VT, это становится почти слишком сложным.
все, что я ищу, это VT, который выглядит как ListView, с подэлементами так далее.
вот некоторые процедуры, использующие ListView, которые я хотел бы использовать с VT (это просто псевдо-пример:
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?
спасибо!
5 ответов
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, просто используйте журнал процедур для отображения информации и измените свой 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;
Почему вы не хотите использовать представление списка в виртуальном режиме? Это будет выглядеть и чувствовать себя правильно и отлично.
Дельфи управления TListView оберткой список компонента Windows вид. В режиме работы по умолчанию копии данных списка передаются из приложения в элемент управления Windows, и это происходит медленно.
альтернативой этому является виртуальное представление списка в терминологии Windows. Приложение не передает данные в элемент управления Windows. Вместо этого, когда элемент управления должен отображать данные, он запрашивает у вашего приложения только необходимые данные.
элемент управления Delphi TListView предоставляет виртуальные представления списка с помощью свойства OwnerData. Вам придется несколько переписать код представления списка, но это не слишком сложно.
Я также предлагаю ссылку на другой вопрос здесь, что покрыло аналогичную землю. Довольно странно, что принятый ответ на этот вопрос говорил о списках, хотя вопрос был о представлении списка контроли.
с VirtualStringTree это немного сложнее, чем простой TListView, однако вот очень простой учебник, который я создал некоторое время назад о том, как использовать VirtualStringTreehttp://www.youtube.com/watch?v=o6FpUJhEeoY я надеюсь, что это поможет, ура!
просто используйте свой обычный TListView, но используйте его в виртуальный режим.
Это очень просто:
- установить
OwnerData
свойствоtrue
- реализовать
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;
вот и все!
некоторые вещи, чтобы иметь в виду:
- вы не вызываете ListView1.Предметы.Добавить (больше).
- вам нужно сохранить свой собственный список данных где-то в памяти или придумать данные в режиме реального времени, поэтому вы больше не можете "хранить" данные в listview.
- вам нужно установить элементы.считай собственность, иначе ничего не увидишь.
- Звонок Мыши Listview1.Update () если что-то изменится.
скачать вклады VT упакуйте и проверьте некоторые из потомков виртуального строкового дерева. Они там. Я не использовал их в проектах, но они, похоже, упрощают использование виртуального строкового дерева.
вот мой начальный праймер, тем не менее:
после использования виртуального строкового дерева я обнаружил, что единственный способ максимально использовать его-реализовать функции init node / child и установить количество корневых узлов, почти такое же, как и представление списка с ownerdraw := true.
Это довольно легко сделать вещи с VirtualStringTree, вам просто нужно реализовать функцию get text и функции размера узла (установите его равным размеру любой записи, которую вы хотели бы использовать в качестве данных за вашим деревом)
Я обнаружил, что это почти всегда проще сделать
TVirtualTreeNodeRecordData = record
Data : TVirtualTreeNodeData;
end
и создайте объект данных в функциях init. Это создает указатели для вас, но вам нужно освободить объекты (опять же, используйте другой обратный вызов узла удаления).