![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Прошу помощи по сохранению TreeView [D7, 2003]
Vervolfe © (2013-09-14 06:34:00)Всех приветствую. Я нашел на этом форуме вот такую статью http://www.delphimaster.net/view/2-1278064750
Пожалуйста, помогите мне разобраться с этим. Уже которую неделю ничего не получается.
wervolfe (2013-09-14 15:38:00) [21]Юрий Зотов
Все! Все прекрасно работает! Ошибся сам. Спасибо, Юрий! Я уже не надеялся что получится как задумано!!!
Здесь нельзя редактировать собственные сообщения? (((
wervolfe (2013-09-14 15:18:00) [22]С первым разобрался. Сделал как в примере.
Вот второе не пойму..((
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 ); // Ошибка. Incompatible Types
TWriter & TReader
End; { While }
reader.ReadListEnd;
finally
reader.Free;
end;
finally
tv.items.Endupdate;
end;
End; { LoadTreeviewFromStream }
wervolfe (2013-09-14 14:54:00) [23]
Procedure SaveTreeviewToStream( tv: TTreeview; S: TStream;
saveProc: TNodeSaveDataProc );
Procedure LoadTreeviewFromStream( tv: TTreeview; S: TStream;
loadProc: TNodeLoadDataProc );
Где и каким образом правильно объявить TNodeLoadDataProc & TNodeSaveDataProc ?
wervolfe (2013-09-14 14:25:00) [24]Спасибо огромное!!!! Сейчас проверю все. Вы не представляете как Вы мне помогли!!!
Юрий Зотов (2013-09-14 14:13:00) [25]Небольшая поправка (так будет лучше):
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;
Юрий Зотов (2013-09-14 14:08:00) [26]> wervolfe © (14.09.13 13:02) [14]
> Я вообще был шоке, когда узнал, то у дерева
> нет этого свойства по умолчанию.
Во-первых, не свойства, а метода. Во-вторых, такого метода нет потому, что его и не может быть - ведь разработчикам дерева тоже неизвестно, какие именно данные собирается хранить программист.
Юрий Зотов (2013-09-14 14:00:00) [27]> wervolfe © (14.09.13 13:02) [14]
Ну, положим, примеры с исходниками в Интернете все же есть - хотя бы, все тот же пример, который Вы обозначили "Вариант 1". Естественно, код в нем неполный - и теперь, надеюсь, Вы понимаете, что полным он быть не может, потому что только Вам (а не автору примера) известно, какие именно данные Вы собираетесь сохранять.
Так что пример есть, просто он рассчитан на немного более "продвинутого" программиста - который понимает, как определить функцию обратного вызова, как ее написать, как работать с указателями и потоками.
Вот те 2 функции обратного вызова, которые нужны для варианта 1:
type
PNodeOptions = ^TNodeOptions;
TNodeOptions = record // Тип переименован - так принято в Delphi
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);
Reader.ReadListBegin;
with P^ do
begin
Name := Reader.ReadString;
Surname := Reader.ReadString;
Address := Reader.ReadString;
EMail := Reader.ReadString;
end;
Reader.ReadListEnd;
Result := P
end;
А вот, собственно, и само сохранение/чтение в варианте 1:
const
FileName = 'D:/Temp/TreeViewWithData.bin';
procedure TForm1.SaveButtonClick(Sender: TObject);
var
S: TFileStream;
begin
S := TFileStream.Create(FileName, fmOpenWrite);
try
SaveTreeViewToStream(TreeView1, S, NodeSaveDataProc);
finally
S.Free;
end;
end;
procedure TForm1.LoadButtonClick(Sender: TObject);
var
S: TFileStream;
begin
S := TFileStream.Create(FileName, fmOpenRead);
try
LoadTreeViewFromStream(TreeView1, S, NodeLoadDataProc);
finally
S.Free;
end;
end;
Писал "с ходу" и код не проверял, поэтому возможны ошибки - ну это уже пусть будет Вашим "домашним заданием". Дебаггер поможет. Ну и спрашивайте, если что (только уже конкретно а не так, как в сабже).
Удачи!
PS
А string[255] лучше заменить на просто string. Во-первых, избавитесь от ограничения длины, а во-вторых (скорее всего) сэкономите память.
wervolfe (2013-09-14 13:02:00) [28]Юрий Зотов . Спасибо за участие.
Сейчас это элементарная программа из учебника Фленова.
unit UnitMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls, Buttons, ExtCtrls;
type
PNodeOptions = ^NodeOptions;
NodeOptions=record
Name: String[255];
Surname: String[255];
Address: String[255];
EMail: String[255];
end;
TMainForm = class(TForm)
TreeView: TTreeView;
Panel1: TPanel;
NewBtn: TBitBtn;
DelBtn: TBitBtn;
SaveBtn: TBitBtn;
Label1: TLabel;
Label2: TLabel;
Label4: TLabel;
Label5: TLabel;
NameEdit: TEdit;
SurnameEdit: TEdit;
AddressEdit: TEdit;
EMailEdit: TEdit;
procedure NewBtnClick(Sender: TObject);
procedure SaveBtnClick(Sender: TObject);
procedure TreeViewChanging(Sender: TObject; Node: TTreeNode;
var AllowChange: Boolean);
procedure DelBtnClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
procedure TMainForm.NewBtnClick(Sender: TObject);
var
NodeName:String;
NodeData:PNodeOptions;
NewNode:TTreeNode;
begin
if not InputQuery('Новый элемент', 'Введите имя нового элемента',
NodeName) then exit;
NewNode:=TreeView.Items.AddChild(TreeView.Selected, NodeName);
// Инициализация начальных данных структуры
NodeData:=new (PNodeOptions);
NodeData.Name:='';
NodeData.Surname:='';
NodeData.Address:='';
NodeData.EMail:='';
NewNode.Data:=NodeData;
end;
procedure TMainForm.SaveBtnClick(Sender: TObject);
begin
if TreeView.Selected=nil then exit;
PNodeOptions(TreeView.Selected.Data).Name:=NameEdit.Text;
PNodeOptions(TreeView.Selected.Data).Surname:=SurnameEdit.Text;
PNodeOptions(TreeView.Selected.Data).Address:=AddressEdit.Text;
PNodeOptions(TreeView.Selected.Data).EMail:=EMailEdit.Text;
end;
procedure TMainForm.TreeViewChanging(Sender: TObject; Node: TTreeNode;
var AllowChange: Boolean);
begin
if Node=nil then exit;
NameEdit.Text:=PNodeOptions(Node.Data).Name;
SurnameEdit.Text:=PNodeOptions(Node.Data).Surname;
AddressEdit.Text:=PNodeOptions(Node.Data).Address;
EMailEdit.Text:=PNodeOptions(Node.Data).EMail;
end;
procedure TMainForm.DelBtnClick(Sender: TObject);
begin
if TreeView.Selected=nil then exit;
TreeView.Selected.Delete;
end;
end.
Если в ней я смогу сохранить данные, то в своей я уже сохраню. Дальше я разберусь. У меня написана достаточно большая программа, которую я писал руководствуясь учебником и примерами из интернета. Она уже готова, полностью работоспособна. Затык только с сохранением сабжа. Примеров с исходниками в интернете нет! Я уже трое суток просто занимаюсь поиском, хоть какого-нибудь законченного примера.
Нашел два приемлемых варианта.
1. http://k210.org/delphi/main/1/- он много где упоминается. Но я не понимаю как получить и считать из него файл. Я вижу, что для этого нужна процедура saveProc ( writer: TWriter; data: Pointer ); однако написать эту процедур я не могу. выше мне было сказано, что это очень просто-для программиста может и просто.
2. http://www.delphimaster.net/view/2-1278064750- здесь тоже два куска, причем, видимо с описками. Некоторых враз я не понимаю (вше спрашивал) и поэтому не могу связать эти части вместе и найти ошибку. Хотя топикстартер там говорит, что она у него заработала.
Больше ничего я найти не могу. Все остальное слишком сложное для меня или просто не по теме.
Программу я пишу для себя. поэтому хлеб ни у кого не отнимаю. Профессионально программированием заниматься не собираюсь, потому что у меня совершенно другой профиль (информационная безопасность (Сертификаты CISCO ASA, КАT6), Программистов у меня знакомых здесь нет. Я здесь в командировке на год.
Поэтому я и прошу посмотреть мои ссылки и помочь свести это в одну работоспособную программу. Я вообще был шоке, когда узнал, то у дерева нет этого свойства по умолчанию.
wervolfe (2013-09-14 11:50:00) [29]Юрий Зотов
Нет. У меня в каждой ноде содержатся текстовые данные. В каждой около 10.
Вот так:
type
PNodeOptions = ^NodeOptions;
NodeOptions=record
Name: String[255];
Surname: String[255];
Address: String[255];
EMail: String[255];
end;
Это из примера, который я пытаюсь сохранить.
wervolfe (2013-09-14 11:46:00) [30]Кирюха -Спасибо. Сейчас посмотрю.
Подскажите вот в этом коде записи из потока в файл есть ошибка в указаной строке? У меня на ней выскакивает ошибка...
SL : tStringList;
N :TTreeNode;
SL:= tStringList.Create;
ANode:= TreeView.Items.GetFirstNode;
while ANode <> nil do
begin
SL.Add(Rec(ANode.Data^).Str); // здесь ругается. Что такое "rec"?
//Правильна ли эта фраза вообще?
n := ANode.GetNext;
end;
SL.SaveToFile("Value.dat");
FreeAndNil(SL);
Юрий Зотов (2013-09-14 11:33:00) [31]> wervolfe © (14.09.13 10:20) [8]
Если Вам нужно сохранить/загрузить только сами ветки дерева, то у TreeView есть методы SaveToFile и LoadFromFile. Они очень простые и описаны в справке, которую Вы, конечно же прочитали (разве не так?). Поэтому проблема непонятна.
const
FileName = 'D:/Temp/TV.nodes';
procedure TForm1.FormCreate(Sender: TObject);
begin
TreeView1.SaveToFile(FileName);
TreeView1.Items.Clear;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
TreeView1.LoadFromFile(FileName);
end;
Если же Вам нужно сохранить/загрузить еще и данные веток (свойство TTreeNode.Data), то ссылку на статью Вам дали, там все расписано. Но, как уже говорилось, Вы должны понимать, что данные бывают разными (текст, рисунок, число, объект и пр.) и поэтому сохраняются/читаются они тоже по-разному. Ну а поскольку никто, кроме Вас, не знает, что это за данные, а Вы о них ничего не сказали, то и дать Вам готовый код невозможно. Либо пользуйтесь статьей самостоятельно (там нужно будет написать 2 процедуры), либо расскажите, какие именно данные Вы хотите сохранять/загружать. Иначе помочь Вам не сможет даже самый добрый программист на свете (ну, Вы уже поняли, что это я, конечно же...).
sniknik (2013-09-14 11:06:00) [32]> что вопросы не задавать в эом форуме-все равно на них никто отвечать не станет.
на ВОПРОСЫ то как раз отвечают, достаточно посмотреть соседние ветки.
> С вашим,sniknik , лично отношением к людям мне все понятно.
не к людям, а лично к тебе... и даже это вопрос, скорее к тому как ты "себя подаешь" в этой ветке.
Кирюха (2013-09-14 11:03:00) [33]Тут вроде про сабж: http://www.cyberforum.ru/delphi/thread608168.html
wervolfe (2013-09-14 10:20:00) [34]У меня нет здесь никаких программистов! Это программа лично для меня. Я над этой проблемой сижу уже неделю безвылазно. В избранном сотни уже ссылок.
Так что не нужно говорить, что не пытался.
Я надеюсь, что все таки найдется человек без понтов, который просто поможет? Или все такие забубенные "программисты" что не могут снизойти до просьбы постороннего? Ну тогда так и напишите, что вопросы не задавать в эом форуме-все равно на них никто отвечать не станет. С вашим,sniknik , лично отношением к людям мне все понятно.
sniknik (2013-09-14 10:10:00) [35]> Извините, если кого обидел!
спасибо я уже пообедал.
> Вам это 10 минут, если очевидно, а я буду изобретать велосипед еще три недели!
вот поэтому у людей есть профессии и каждый профессионал занимается своим делом.
найми программиста. ну или изобретай велосипед три недели, больше поводов буде в следующий раз нанять программиста. ему тоже есть надо ... ты же не пойдешь к нему сеть прокладывать на основании что тебе это 10 мин, а ему три недели ковыряться.
wervolfe (2013-09-14 09:46:00) [36]Да. Удаление и добавление понятно. Данные вводятся в TEdit. Все text. Все до 255. Не более десяти полей. Я заполняю дерево и мне его нужно сохранить кликом кнопки в файл. При открытии формы (или по клику-не суть) загрузить назад. Все.
wervolfe (2013-09-14 09:42:00) [37]Я предупредил в первом сообщении, что я не программист. Я работаю с сетями и мне 43 года! Это разовая программа для автоматизации одного процесса.
Я ее уже написал. Весь затык только в сохранении дерева. Я вообще плохо себе представляю что такое стрим, как работают указатели и пр. Поэтому я и попросил помощи в примере. Извините, если кого обидел!
"но есть же "стрим в файл", стандартный. все очевидно." - это Вам очевидно. Если очевидно-ну затратьте, пожалуйста, 10 мин своего времени и напишите пример, чтобы до сохранения файла. И такой же загрузки. Вам это 10 минут, если очевидно, а я буду изобретать велосипед еще три недели!
Туповатый (2013-09-14 09:40:00) [38]Я дал Вам ссылку "Как правильно задавать вопросы" а не в поиск отправлял.
На Ваш текущий общий вопрос ответа не будет, по крайней мере от меня, пока не будет точной формулировки требуемого и попыток самостоятельного решения.
Вы хотя бы понимаете, что данные бывают разные? Текст, картинки, объекты?
Файлы, они, конечно, все из байтов, но зато структура этих байтов так же разная, не говоря уже о некотором количестве стандартов форматов.
И судя по всему, на экране это дерево уже отображается, перебор веток понятен, равно как и удаление-добавление-изменение?
sniknik (2013-09-14 09:33:00) [39]> ответить на вопрос - помочь разобраться с сохранением данных TreeView в файл? В сети я не нашел ответа.
потому, что это не вопрос.
> Объясните тогда как работать с ней!
там код для копипаста, это высшая форма объяснений... ну сохраняет только не файл, а в стрим, но есть же "стрим в файл", стандартный. все очевидно.
тебе не объяснения нужны, а багаж базовых знаний.
> Или все горазды только в поиск отправлять?
и кто тебя здесь отправил в поиск? хотя это дело хорошее, учится искать... но здесь тебе явно привели ссылку на статью которая точно поможет... если советам из нее следовать. и которую ты явно проигнорировал судя по посту после нее.
wervolfe (2013-09-14 08:29:00) [40]Тем не менее, кто-нибудь может ответить на вопрос - помочь разобраться с сохранением данных TreeView в файл? В сети я не нашел ответа.
Есть несколько ссылок вот на эту процедуру : http://k210.org/delphi/main/1/
Объясните тогда как работать с ней! Или все горазды только в поиск отправлять?