Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 24.02.2014, 04:17
Toxa16 Toxa16 вне форума
Прохожий
 
Регистрация: 24.02.2009
Сообщения: 2
Репутация: 10
По умолчанию Сохранение данных TreeView

Есть TreeView, к узлам привязаны данные.
Такая вот структура:
Код:
type
  PNodeOptions = ^NodeOptions;
  NodeOptions=record
   Name: String[255];
   Surname: String[255];
   Address: String[255];
   EMail: String[255];
  end;

Пожалуйста, помогите эти данные записывать и считывать из файла! Чтобы и дерево, и эти привязанные данные были в одном файле. Я обыскал все, ничего путного не нашел(((
Очень нужна помощь!
Ответить с цитированием
  #2  
Старый 24.02.2014, 04:35
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,015
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Ну так и сериализуй.
Тут надо знать как узлы в дереве расположены (сколько корневых).
Можно просто в xml сериализовать, тогда меньше мороки с корневыми узлами, но больше потом мороки с чтением всего этого добра обратно.
Ответить с цитированием
  #3  
Старый 24.02.2014, 08:18
Аватар для Alegun
Alegun Alegun вне форума
LMD-DML
 
Регистрация: 12.07.2009
Адрес: Богородское
Сообщения: 3,025
Версия Delphi: D7E
Репутация: 1834
По умолчанию

А что если радикально, пользуя сам компонет, через файловый поток
Код:
var
  fs: TFileStream;
  ...
{Сохранить} fs:= TFileStream.Create('tv.sav', fmCreate or fmShareCompat);
{Загрузить} fs:= TFileStream.Create('tv.sav', fmOpenRead or fmShareDenyWrite);
  try
{Сохранить} fs.WriteComponent(TreeView1);
{Загрузить}  fs.ReadComponent(TreeView1);
   finally
    fs.Free;
  end;
  ...
Ответить с цитированием
  #4  
Старый 24.02.2014, 09:24
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,015
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Цитата:
Сообщение от Alegun
А что если радикально, пользуя сам компонет, через файловый поток

Не, если я правильно помню, то он привязанные данные не сохраняет, просто в силу того, что не знает как это делать.
Ответить с цитированием
  #5  
Старый 24.02.2014, 12:27
Toxa16 Toxa16 вне форума
Прохожий
 
Регистрация: 24.02.2009
Сообщения: 2
Репутация: 10
По умолчанию

Не работает, файловый поток сохраняет только само дерево, без данных!( еще варианты?
Ответить с цитированием
  #6  
Старый 24.02.2014, 15:12
Аватар для Alegun
Alegun Alegun вне форума
LMD-DML
 
Регистрация: 12.07.2009
Адрес: Богородское
Сообщения: 3,025
Версия Delphi: D7E
Репутация: 1834
По умолчанию

Следуя вот этим рекомендациям вырисовывается лишь связка из сохранения структуры дерева в отдельном файле (см. код выше) и данных из нод, но так же в отдельном файле
Код:
...
type
 PNodeOptions = ^TNodeOptions;
 TNodeOptions = record
  Name:    string[255];
  Surname: string[255];
  Address: string[255];
  EMail:   string[255];
 end;

procedure NodeSaveDataProc(Writer: TWriter; Data: Pointer);
begin
 Writer.WriteListBegin;
 with TNodeOptions(Data^) do
 begin
  Writer.WriteString(Name);
  Writer.WriteString(Surname);
  Writer.WriteString(Address);
  Writer.WriteString(EMail);
 end;
 Writer.WriteListEnd;
end;

function NodeLoadDataProc(Reader: TReader): Pointer;
var
 P: PNodeOptions;
begin
 New(P);
 try
   Reader.ReadListBegin;
   with P^ do
   begin
    Name:=    Reader.ReadString;
    Surname:= Reader.ReadString;
    Address:= Reader.ReadString;
    EMail:=   Reader.ReadString;
   end;
   Reader.ReadListEnd;
 except
  Dispose(P);
  raise;
 end;
 Result:= P;
end;

type
TNodeSaveDataProc = procedure(Writer: TWriter; data: Pointer);
TNodeLoadDataProc = function(Reader: TReader): Pointer;

procedure SaveTreeviewToStream(tv: TTreeview; S: TStream;
saveProc: TNodeSaveDataProc);
var
  Writer: TWriter;
  Node:   TTreeNode;
begin
  Assert(Assigned(tv));
  Assert(Assigned(S));
  Assert(Assigned(saveProc));
  Writer:= TWriter.Create(S, 4096);
  try
    Node:= tv.Items[0];
    Writer.WriteListBegin;
    while Node <> nil do
    begin
     Writer.WriteInteger(Node.Level);
     Writer.WriteString(Node.Text);
     Writer.WriteInteger(Node.ImageIndex);
     saveProc(Writer, Node.Data);
     Node:= Node.GetNext;
    end; { While }
    Writer.WriteListEnd;
    Writer.FlushBuffer;
  finally
    Writer.Free;
  end;
end; { SaveTreeviewToStream }

procedure LoadTreeviewFromStream(tv: TTreeview; S: TStream;
                  loadProc: TNodeLoadDataProc);
var
  Reader: TReader;
  Node:   TTreeNode;
  Level:  integer;
begin
  Assert(Assigned(tv));
  Assert(Assigned(S));
  Assert(Assigned(loadProc));
  tv.Items.BeginUpdate;
  try
    tv.Items.Clear;
    Reader:= TReader.Create(S, 4096);
    try
      Node:= nil;
      Reader.ReadListBegin;
      while not Reader.EndOfList do begin
        Level := Reader.ReadInteger;
        if Node = nil then
        // create root node, ignore its level
          Node:= tv.Items.Add(nil, '')
        else
        begin
          if Level = Node.Level then
            Node:= tv.Items.Add(node, '')
          else if Level > Node.Level then
            Node:= tv.Items.AddChild(Node, '')
          else begin
            while Assigned(Node) and (Level < Node.Level) do
            Node:= Node.Parent;
            Node:= tv.Items.Add(node, '');
          end; { Else }
        end; { Else }
        Node.Text:= Reader.ReadString;
        Node.ImageIndex:= Reader.ReadInteger;
        Node.Data:= loadProc(Reader);
      end; { While }
      Reader.ReadListEnd;
    finally
      Reader.Free;
    end;
  finally
    tv.items.Endupdate;
  end;
end; { LoadTreeviewFromStream }

procedure TForm1.Button1Click(Sender: TObject);
var
 S: TFileStream;
begin
 S := TFileStream.Create('Data.sav', fmCreate or fmShareCompat);
 try
   SaveTreeViewToStream(TreeView1, S, NodeSaveDataProc);
 finally
   S.Free;
 end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
 S: TFileStream;
begin
 S := TFileStream.Create('Data.sav', fmOpenRead);
 try
   LoadTreeViewFromStream(TreeView1, S, NodeLoadDataProc);
 finally
   S.Free;
 end;
end;
с последующей загрузкой. Если необходим один файл, то можно попробовать сливать их вместе, а затем резать в памяти на два куска, но есть ли в этом смысл, загадка
Ответить с цитированием
  #7  
Старый 24.02.2014, 20:47
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,015
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Думаю, что смысла нет. Скорее всего, дерево обеспечивает только структуру (хотя я не знаю, какая информация "сидит" в заголовке самих нод, если просто объединение тех же данных, что и в прикрепленной записи, то смысла сохранения дерева нет вообще). В этом случае достаточно просто писать все ноды в отдельный файл (поток), а при чтении восстанавливать структуту по файлу.

ЗЫ. Писать код просто влом, там все достаточно просто. Сначала пишется кол-во корневых узлов, потом сами узлы и, рекурсивно, все их подузлы. При чтении - в обратном порядке. Вот псевдокод:
Код:
procedure SaveTree(Stream : TStream);
var
  I : Integer;
begin
  WriteToStream(Stream,RootTreeCount);
  For I := 0 To RootTreeCount-1 Do
    SaveNode(Stream,Nodes[i]);
end;

procedure SaveNode(Stream : TStream; Node : TTreeNode);
var
  I : Integer;
begin
  WriteToStream(Stream,Node.Data);
  WriteToStream(Stream,Node.Items.Count);
  For I := 0 To Node.Items.Count-1 Do
    SaveNode(Stream,Node.Items[i]);
end;
Чтение, соотв. наоборот, с созданием нужных узлов.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 02:31.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter