delphi 如何保存一个包含所有节点及其记录对象的Treeview?

9rbhqvlz  于 2023-05-06  发布在  其他
关注(0)|答案(2)|浏览(146)

如何保存一个包含所有节点及其记录对象的树视图?当从表中的blob字段加载时,然后当我单击节点时,显示存储在node.data中的信息。
我有这个:

type
  PMyRec = ^TMyRec;
  TMyRec = record
   text:string;
   codigo:string;
   medida:string;
   parent:string;
   ativo:String;
   Tipo: string;
   wasExpanded:boolean;
  end;
var
  Form1: TForm1;
  MyRecPtr: PMyRec;

当我添加一个节点时:

New(MyRecPtr);
         MyRecPtr^.Tipo := 'R';
         MyRecPtr^.codigo := edit1.text;
         MyRecPtr^.parent := edit3.text;
         MyRecPtr^.text := edit2.Text;

         Tree1.Items.AddChildObject(nil,ansiuppercase(edit1.text+' '+edit2.text),MyRecPtr);

当用户在树的项目中点击时:

Node:=tree1.Selected;

    if PMyRec(Node.Data)^.Tipo='R' then
      begin
       edit1.Text:=PMyRec(Node.Data)^.codigo;
       edit2.Text:=PMyRec(Node.Data)^.text;
       edit3.Text:=PMyRec(Node.Data)^.parent;
      end;

我有一棵树,上面有4000多个项目!从一个存储的文件中一项一项地读取,然后为每一个创建一个记录点是极其缓慢的!但是当保存为Tmemorystream blob时,它们的加载速度很快,但是记录对象没有保存。
是可能的想法或给予例子如何保存一个树和所有记录对象附加,以便当从文件加载时,点击一个节点,然后显示信息从他们的记录对象附加?
坦斯克
我在网上看了很多东西,但是没有作品
我发现这个:text
当保存对象转换成一个整数“writer.WriteInteger(Integer(node.data))”,然后当加载转换成一个指针“node.Data:= Pointer(Reader.ReadInteger)”,但当点击树的项目时会出现错误!我认为没有内存分配。

7vux5j2d

7vux5j2d1#

你写的数据地址,在另一个进程中没有意义.如果所有节点数据包含相同的记录类型,则必须更改(我没有检查树保存-恢复的整体正确性):

writer.WriteInteger(Integer(node.data));

...到序列:

writer.WriteString(PMyRec(Node.Data)^.text);
...
writer.WriteString(PMyRec(Node.Data)^.Tipo);
writer.WriteBoolean(PMyRec(Node.Data)^.wasExpanded);

类似地,而不是:

node.Data := Pointer(Reader.ReadInteger);

...用途:

New(MyRecPtr);
MyRecPtr^.text := Reader.ReadString;

等等,最后:

node.Data := MyRecPtr;
zu0ti5jz

zu0ti5jz2#

您需要一个解析器来将数据传入和传出blob。用于此的数据格式的示例是JSON、XML、…或诸如TReader + TWriter等的组件。然而,这种实现需要进一步的知识。所以我会用我自己的解析器从已知到未知。在我的示例中,我使用ToString和FromString方法将解析器直接附加到记录。现在必须从数据库字段读取或保存字符串。

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, system.Math, Data.DB;

type
  TMyRec = record
  public
    const DELIM='###';
  constructor Create(Data: string);
  public
    text:string;
    codigo:string;
    medida:string;
    parent:string;
    ativo:String;
    Tipo: string;
    wasExpanded:boolean;
  public
    function ToString: string;
    procedure FromString(Value: string);
  end;

  { TMyRec }

  constructor TMyRec.Create(Data: string);
  begin
    FromString(Data);
  end;

  procedure TMyRec.FromString(Value: string);
  var
   i: integer;
   a: TArray<string>;
  begin
    Self := Default(TMyRec);
    a    := Value.Split([DELIM]);
    for i := 0 to Min(length(a), 7) do
    case i of
      0: text          := a[0]; //or a[i]
      1: codigo        := a[1];
      2: medida        := a[2];
      3: parent        := a[3];
      4: ativo         := a[4];
      5: Tipo          := a[5];
      6: wasExpanded   := boolean(StrToIntDef(a[6], 0));
    end;
  end;

  function TMyRec.ToString: string;
  begin
    //                0   1   2   3   4   5   6
    Result := Format('%s%s%s%s%s%s%s%s%s%s%s%s%d%',
    //                0            1              2              3
                     [text, DELIM, codigo, DELIM, medida, DELIM, parent, DELIM,
    //                4             5            6
                      ativo, DELIM, Tipo, DELIM, ord(wasExpanded)]);

  end;

  var
    s : string;
    r : TMyRec;
    db: TDataSet;
  begin
    try
      //Test-->
      r         := Default(TMyRec);
      r.text    := 'ABC';
      r.codigo  := 'DEF';
      r.medida  := 'GHI';
      r.ativo   := 'JKL';
      r.Tipo    := 'MNO';
      r.wasExpanded := True;

      //save
      s := r.ToString;
      writeln(s);

      //load
      r := Default(TMyRec);
      r := TMyRec.Create(s);
      s := r.ToString;
      writeln(s);
      //<<--Test

      { TODO : With Databaseconnection
      db.FieldByName('abc').AsString := r.ToString;
      r :=  TMyRec.Create(db.FieldByName('abc').AsString);
      }
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

相关问题