Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Синхронизация нескольких VirtualStringTrees с одной копией данных в Delphi

Delphi , Синтаксис , Деревья

В современных приложениях часто бывает необходимо отображать иерархические данные в нескольких местах с незначительными изменениями в способе отображения. Одним из способов достижения этого является использование компонента VirtualStringTree в Delphi. Однако, при использовании этого компонента может возникнуть проблема с дублированием данных, если для каждого экземпляра дерева создается отдельная копия данных.

В данной статье мы рассмотрим, как синхронизировать несколько VirtualStringTrees с одной копией данных в Delphi. Мы покажем, как создать "мастер"-дерево, которое будет ссылаться на фактические данные, и несколько "рабынь"-деревьев, которые будут ссылаться на те же данные.

Для начала давайте посмотрим на пример кода, который был представлен в контексте:

// Initialize the NodeDataSize
procedure TForm1.FormCreate(Sender: TObject);
begin
    TreeMasterComponents.NodeDataSize := SizeOf(rMasterComponent);
    VST.NodeDataSize := SizeOf(Pointer);
end;

// Procedure to copy the master tree to slave trees
procedure TForm1.LoadSlaveTree(ATree: TVirtualStringTree);
var Node : PVirtualNode;

procedure RecursiveCopy(SrcPNode, SrcTNode : PVirtualNode; ATree : TVirtualStringTree);
var SrcNode, TargetNode : PVirtualNode;
    SrcData : PMasterComponent;
begin
    SrcNode := TreeMasterComponents.GetFirstChild(SrcPNode);
    while Assigned(SrcNode) do
    begin
        SrcData := TreeMasterComponents.GetNodeData(SrcNode);
        TargetNode := ATree.AddChild(SrcTNode, SrcData);
        RecursiveCopy(SrcNode, TargetNode, ATree);
        SrcNode := SrcNode.NextSibling;
    end;
end;

begin
    ATree.BeginUpdate;
    ATree.Clear;
    Node := TreeMasterComponents.GetFirst(true);
    while Assigned(Node) do
    begin
        RecursiveCopy(Node, nil, ATree);
        Node := Node.NextSibling;
    end;
    ATree.EndUpdate;
end;

// Procedure for slave tree to getCellText
procedure TForm1.SlaveGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
    Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var Data : PMasterComponent;
begin
    Data := Sender.GetNodeData(Node);
    Case Column of
        0: CellText := Data^.ComponentCode;
        1: CellText := Data^.FullLocation;
    end;
end;

В этом примере мы видим, что мастер-дерево инициализируется с размером NodeData, равным размеру структуры MasterComponent. Затем мы видим процедуру LoadSlaveTree, которая копирует мастер-дерево в каждое из раб-деревьев. Для этого используется процедура RecursiveCopy, которая рекурсивно копирует все дочерние узлы текущего узла. Наконец, мы видим процедуру SlaveGetText, которая используется раб-деревьями для получения текста ячейки для каждого узла.

Однако, как видно из примера, при текущем подходе текст не отображается в раб-деревьях. Причиной этого является то, что мы пытаемся直接 использовать указатель на структуру MasterComponent в качестве NodeData для раб-деревьев, что приводит к неправильному отображению данных.

Чтобы решить эту проблему, нам нужно создать neuen запись, которая будет содержать указатель на оригинальные данные:

type
    PRefMasterComponent = ^RefMasterComponent;
    RefMasterComponent = packed record
        PMCData: PMasterComponent;
    end;

Теперь мы можем инициализировать размер NodeData для раб-деревьев как размер этой новой записи:

procedure TForm1.FormCreate(Sender: TObject);
begin
    TreeMasterComponents.NodeDataSize := SizeOf(rMasterComponent);
    VST.NodeDataSize := SizeOf(RefMasterComponent);
end;

Далее, нам нужно изменить процедуру LoadSlaveTree, чтобы использовать эту новую запись для хранения указателя на оригинальные данные:

procedure TForm1.LoadTree(ATree: TVirtualStringTree);
var
    Node, TargetNode: PVirtualNode;
    SrcData: PMasterComponent;
    Data: PRefMasterComponent;
procedure RecursiveCopy(SrcPNode, TargetPNode: PVirtualNode; ATree: TVirtualStringTree);
var
    Node, TargetNode: PVirtualNode;
    SrcData: PMasterComponent;
    Data: PRefMasterComponent;
begin
    Node := TreeMasterComponents.GetFirstChild(SrcPNode);
    while Assigned(Node) do
    begin
        SrcData := TreeMasterComponents.GetNodeData(Node);
        TargetNode := ATree.AddChild(TargetPNode);
        Data := ATree.GetNodeData(TargetNode);
        Data.PMCData := SrcData;
        RecursiveCopy(Node, TargetNode, ATree);
        Node := Node.NextSibling;
    end;
end;
begin
    ATree.BeginUpdate;
    ATree.Clear;
    Node := TreeMasterComponents.GetFirst(true);
    while Assigned(Node) do
    begin
        SrcData := TreeMasterComponents.GetNodeData(Node);
        TargetNode := ATree.AddChild(nil);
        Data := ATree.GetNodeData(TargetNode);
        Data.PMCData := SrcData;
        RecursiveCopy(Node, TargetNode, ATree);
        Node := Node.NextSibling;
    end;
    ATree.EndUpdate;
end;

Наконец, нам нужно изменить процедуру SlaveGetText, чтобы использовать эту новую запись для получения данных:

procedure TForm1.vstGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
    Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var
    Data: PRefMasterComponent;
    RefData: PMasterComponent;
begin
    Data := Sender.GetNodeData(Node);
    RefData := Data.PMCData;
    case Column of
        0: CellText := RefData.ComponentCode;
        1: CellText := RefData.FullLocation;
    end;
end;

Теперь, когда мы изменяем данные в одном дереве, мы можем просто вызвать VST.Invalidate, чтобы отразить изменения в других деревах.

В заключение, мы рассмотрели, как синхронизировать несколько VirtualStringTrees с одной копией данных в Delphi. Мы показали, как создать "мастер"-дерево, которое будет ссылаться на фактические данные, и несколько "рабынь"-деревьев, которые будут ссылаться на те же данные. При правильном использовании этой техники можно добиться значительной экономии памяти и упрощения кода.

Создано по материалам из источника по ссылке.

В данном контексте рассматривается решение задачи синхронизации нескольких деревьев VirtualStringTree с одной копией данных в Delphi, чтобы избежать дублирования данных при создании отдельной копии для каждого дерева. Для этого предлагается создать "масте


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Деревья ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-11-21 13:20:46/0.0056910514831543/1