有什么方法可以将本地存储(在文件中)TVirtualStringTree
作为特定节点下的子树添加到另一个文件中?
在示例中,为了速度起见,我使用了TTreeView
,但是我需要使用TVirtualStringTree
。我试图找到有关此方法的一些信息。
{ TBaseVirtualTree.AddFromStream Method
Adds the content from the given stream to the given node. }
procedure AddFromStream(Stream: TStream; TargetNode: PVirtualNode);
{ Description
AddFromStream restores the subtree stored in Stream and adds it to
TargetNode. The content of the stream must have been saved previously with
SaveToStream. }
哪种情况最合适,因为我需要将先前保存的树添加到特定节点(在示例中为选定的树)。但是我在网上找不到任何有关它的信息,也没有实际的例子。那么如何将已保存的树(其所有内容)还原为所选节点下的子树?
答案 0 :(得分:1)
要将特定节点及其虚拟树的子节点存储到文件中,必须使用方法SaveToStream
,该方法不同于SaveToFile
接受源节点的可选参数:
procedure SaveNodeToFile(ATree: TBaseVirtualTree; ANode: PVirtualNode;
AFileName: String);
var
stream: TFileStream;
begin
stream := TFileStream.Create(AFileName, fmCreate);
try
ATree.SaveToStream(stream, ANode);
finally
stream.Free;
end;
end;
由于虚拟树对数据一无所知,因此必须提供一种方法来写入分配给每个节点的数据。树为此提供了事件OnSaveNode
。在这里,我假设节点在包含字符串“ Caption”的记录中有数据(或者,当然,您必须根据需要对其进行调整):
type
PTreeData = ^TTreeData;
TTreeData = record
Caption: String;
end;
procedure TForm1.VirtualStringTree1SaveNode(Sender: TBaseVirtualTree;
ANode: PVirtualNode; Stream: TStream);
var
data: PTreeData;
n: Integer;
begin
// Get pointer to the node's data
data := Sender.GetNodeData(ANode);
// Write the length of the string (in characters)
n := Length(data^.Caption);
Stream.WriteDWord(n);
if n > 0 then
// write the string characters
Stream.Write(data^.Caption[1], Length(data^.Caption) * SizeOf(char));
end;
为了将文件读回到另一棵树的节点,您已经提到的方法AddFromStream
是完美的:
procedure LoadNodeFromFile(ATree: TBaseVirtualTree; ANode: PVirtualNode; AFileName: String);
var
stream: TFileStream;
begin
stream := TFileStream.Create(AFileName, fmOpenRead);
try
ATree.AddFromStream(stream, ANode);
finally
stream.Free;
end;
end;
同样,您需要告诉树如何获取分配给每个节点的数据-事件OnLoadNode
的处理程序必须与OnSaveNode
事件完全相反:
procedure TForm1.VirtualStringTree2LoadNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
Stream: TStream);
var
data: PTreeData;
n: DWord;
begin
// Get pointer to the node's data
data := Sender.GetNodeData(Node);
// Read the string length (in characters)
n := Stream.ReadDWord;
if n > 0 then begin
// Set the length of the string
SetLength(data^.Caption, n);
if n > 0 then
// Read the string's characters
Stream.Read(data^.Caption[1], n * SizeOf(char));
end;
end;
答案 1 :(得分:0)
EDIT :已解决,需要添加getnodedatasize事件:
procedure TfrmBuilder.VST1GetNodeDataSize(Sender: TBaseVirtualTree;
var NodeDataSize: Integer);
begin
NodeDataSize := SizeOf(TTreeData);
end;
没有树就不会加载。
谢谢
我要重新打开这个主题,还有另一个问题,就是:
我可以使用包含字符串的两列来完美地保存和加载:
type
PTreeData = ^TTreeData;
TTreeData = record
Fname: String;
quant: String;
End;
procedure TfrmBuilder.VST1LoadNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
Stream: TStream);
var
data: PTreeData;
n: DWord;
begin
// Get pointer to the node's data
data := Sender.GetNodeData(Node);
// Read the string length (in characters)
n := Stream.ReadDWord;
if n > 0 then begin
// Set the length of the string
SetLength(data^.Fname, n);
if n > 0 then
// Read the string's characters
Stream.Read(data^.Fname[1], n * SizeOf(char));
end;
n := Stream.ReadDWord;
if n > 0 then begin
// Set the length of the second string
SetLength(data^.quant, n);
if n > 0 then
// Read the second string's characters
Stream.Read(data^.quant[1], n * SizeOf(char));
end;
end;
procedure TfrmBuilder.VST1SaveNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
Stream: TStream);
var
data: PTreeData;
n: Integer;
begin
// Get pointer to the node's data
data := Sender.GetNodeData(Node);
// Write the length of the string (in characters)
n := Length(data^.Fname);
Stream.WriteDWord(n);
if n > 0 then
begin
// write the string characters
Stream.Write(data^.Fname[1], Length(data^.Fname) * SizeOf(char));
end;
// Write the length of the second string (in characters)
n := Length(data^.quant);
Stream.WriteDWord(n);
if n > 0 then
begin
// write the second string chars
Stream.Write(data^.quant[1], Length(data^.quant) * SizeOf(char));
end;
end;
但是,当我尝试使用相同的方法(将字符串写入流中)保存三列时,它将在可执行文件的第一次运行时加载,但是当我关闭exe时,请重新打开并尝试执行重新加载它会给出一个错误sisegv,换句话说就是内存访问冲突
type
PTreeData = ^TTreeData;
TTreeData = record
Fname: String;
quant: String;
OBS: string;
End;
procedure TfrmBuilder.VST1LoadNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
Stream: TStream);
var
data: PTreeData;
n: DWord;
begin
// Get pointer to the node's data
data := Sender.GetNodeData(Node);
// Read the string length (in characters)
n := Stream.ReadDWord;
if n > 0 then begin
// Set the length of the string
SetLength(data^.Fname, n);
if n > 0 then
// Read the string's characters
Stream.Read(data^.Fname[1], n * SizeOf(char));
end;
n := Stream.ReadDWord;
if n > 0 then begin
// Set the length of the second string
SetLength(data^.quant, n);
if n > 0 then
// Read the second string's characters
Stream.Read(data^.quant[1], n * SizeOf(char));
end;
{ THE CODE FOR THE THIRD STRING:
n := Stream.ReadDWord;
if n > 0 then begin
// Set the length of the THIRD string
SetLength(data^.OBS, n);
if n > 0 then
// Read the THIRD string's characters
Stream.Read(data^.OBS[1], n * SizeOf(char));
end;
}
end;
procedure TfrmBuilder.VST1SaveNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
Stream: TStream);
var
data: PTreeData;
n: Integer;
begin
// Get pointer to the node's data
data := Sender.GetNodeData(Node);
// Write the length of the string (in characters)
n := Length(data^.Fname);
Stream.WriteDWord(n);
if n > 0 then
begin
// write the string characters
Stream.Write(data^.Fname[1], Length(data^.Fname) * SizeOf(char));
end;
// Write the length of the second string (in characters)
n := Length(data^.quant);
Stream.WriteDWord(n);
if n > 0 then
begin
// write the second string chars
Stream.Write(data^.quant[1], Length(data^.quant) * SizeOf(char));
end;
{
// Write the length of the THIRD string (in characters)
n := Length(data^.OBS);
Stream.WriteDWord(n);
if n > 0 then
begin
// write the THIRD string chars
Stream.Write(data^.OBS[1], Length(data^.OBS) * SizeOf(char));
end;
}
end;
可能是什么?对于2个字符串(2列),它就像一个符咒,但是对于三个字符串,我却出现访问冲突?
预先感谢, 莱昂纳多
PS:我正在尝试保存/加载的网格图片
如图所示,它有两列,第一列来自data ^ .fname,第二列来自data ^ .quant,第三列应该来自data ^ .OBS,但它只是没有加载(sigsegv),所以我选择了出来。