IPB
ЛогинПароль:

> ВНИМАНИЕ!

Прежде чем задать вопрос, смотрите FAQ.
Рекомендуем загрузить DRKB.

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

3 страниц V < 1 2 3 >  
 Ответить  Открыть новую тему 
> иерархическая структура объектов, Delphi 7
сообщение
Сообщение #21


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Снова вопрос по Drag&Drop..теперь в пределах TreeView..т.е. перемещение узлов.
Нашла в DRKB пример по этому вопросу...

procedure TFormMain.MoveNode(TargetNode, SourceNode: TTreeNode);
var
nodeTmp: TTreeNode;
i: Integer;
begin
with TreeViewNew do
begin
nodeTmp := Items.AddChild(TargetNode, SourceNode.Text);
for i := 0 to SourceNode.Count - 1 do
begin
MoveNode(nodeTmp, SourceNode.Item[i]);
end;
end;
end;

procedure TFormMain.TreeViewNewDragDrop(Sender, Source: TObject; X,
Y: Integer);
var
TargetNode, SourceNode: TTreeNode;
begin
with TreeViewNew do
begin
TargetNode := GetNodeAt(X, Y); // Get target node
SourceNode := Selected;
if (TargetNode = nil) then
begin
EndDrag(False);
Exit;
end;
MoveNode(TargetNode, SourceNode);
SourceNode.Free;
end;
end;

procedure TFormMain.TreeViewNewDragOver(Sender, Source: TObject; X,
Y: Integer; State: TDragState; var Accept: Boolean);
begin
if (Sender = TreeViewNew) then // If TRUE than accept the draged item
begin
Accept := True;
end;
end;


Узлы перемещаются..Но проблема в том, чтобы переместить ещё и связанный с узлом объект...
Объясните пожалуйста, как это нужно делать?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #22


Гость






   nodeTmp := Items.AddChild(TargetNode, SourceNode.Text);

попробуй заменить на
   nodeTmp := Items.AddChildObject(TargetNode, SourceNode.Text, SourceNode.Data);

Должно сработать...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #23


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(volvo @ 8.12.2008 22:33) *

   nodeTmp := Items.AddChild(TargetNode, SourceNode.Text);

попробуй заменить на
   nodeTmp := Items.AddChildObject(TargetNode, SourceNode.Text, SourceNode.Data);

Должно сработать...

Да, получилось!! Спасибо!
И теперь момент, который мне не ясен..И это реализация сохранения (того, что получили на TreeViewNew)/считывания (занесение данных в TreeViewNew) в формате XML...Как это реализуется? Какие-нибудь специальные компоненты? Объясните пожалуйста, как это должно выглядеть??
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #24


Гость






Цитата
как это должно выглядеть??
Вот тут есть описание (правда по-английски): Exporting a TreeView to XML. Populating a TreeView from XML

Правда приведенные там процедуры чтения/записи XML потребуют небольшой доработки, поскольку кроме самих названий узлов у тебя должны сохраняться еще и связанные с ними данные (это придется добавить несколько атрибутов в ProcessTreeItem), и потом они должны восстанавливаться из файла (это в ProcessNode, чтение этих атрибутов, создание экземпляра класса TBPeriod и использование AddChildObject вместо AddChild)...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #25


Гость






А скажите пожалуйста, где будет лежать создаваемый таким образом файлик *.XML?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #26


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(Гость @ 9.12.2008 3:13) *

А скажите пожалуйста, где будет лежать создаваемый таким образом файлик *.XML?

 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #27


Гость






Судя по строке
XMLDoc.SaveToFile(ChangeFileExt(ParamStr(0),'.XML'));
, там же, где и EXE-шник.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #28


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(volvo @ 9.12.2008 0:23) *

Вот тут есть описание (правда по-английски): Exporting a TreeView to XML. Populating a TreeView from XML

Правда приведенные там процедуры чтения/записи XML потребуют небольшой доработки, поскольку кроме самих названий узлов у тебя должны сохраняться еще и связанные с ними данные (это придется добавить несколько атрибутов в ProcessTreeItem)...

А что это за атрибуты?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #29


Гость






Твои атрибуты... Смотри, сохранять дерево (вместе с тем, что хранится в объектах, связанных с узлами), можно так:
procedure Tree2XML(tree: TTreeView);
var
tn : TTreeNode;
XMLDoc : TXMLDocument;
iNode : IXMLNode;

procedure ProcessTreeItem(tn: TTreeNode; iNode: IXMLNode);
var cNode : IXMLNode;
begin
if tn = nil then Exit;

cNode := iNode.AddChild('item');
cNode.Attributes['text'] := tn.Text;
cNode.Attributes['imageIndex'] := tn.ImageIndex;
cNode.Attributes['stateIndex'] := tn.StateIndex;
// Вот это и есть твой атрибут ...
if tn.Data <> nil then begin
cNode.Attributes['sData'] := TBPeriod(tn.Data).sData;
end
else cNode.Attributes['sData'] := '';

tn := tn.getFirstChild;
while tn <> nil do begin
ProcessTreeItem(tn, cNode);
tn := tn.getNextSibling;
end;
end; (*ProcessTreeItem*)

begin
XMLDoc := TXMLDocument.Create(nil);
XMLDoc.Active := True;
iNode := XMLDoc.AddChild('tree2xml');
iNode.Attributes['app'] := ParamStr(0);

tn := tree.TopItem;
while tn <> nil do begin
ProcessTreeItem (tn, iNode);
tn := tn.getNextSibling;
end;
XMLDoc.SaveToFile(ChangeFileExt(ParamStr(0),'.XML'));
XMLDoc := nil;
end; (* Tree2XML *)

procedure TForm1.btnSaveXMLClick(Sender: TObject);
begin
Tree2XML(TreeView1);
end;
Чтобы восстановить из XML сохраненное таким образом дерево:
procedure XML2Tree(tree: TTreeView; XMLDoc: TXMLDocument);
var
iNode : IXMLNode;

procedure ProcessNode(Node : IXMLNode; tn: TTreeNode);
var
cNode : IXMLNode;
newPeriod: TBPeriod;
begin
if Node = nil then Exit;

with Node do begin
// Есть сохраненные атрибуты? Восстанавливаем ...
if Attributes['sData'] <> '' then begin
newPeriod := TBPeriod.Create(
Attributes['text'], Attributes['sData']
);
tn := tree.Items.AddChildObject(
tn, Attributes['text'], newPeriod as TObject
);
end
else // Нету? И не надо ...
tn := tree.Items.AddChild(tn, Attributes['text']);

tn.ImageIndex := Integer(Attributes['imageIndex']);
tn.StateIndex := Integer(Attributes['stateIndex']);
end;

cNode := Node.ChildNodes.First;
while cNode <> nil do begin
ProcessNode(cNode, tn);
cNode := cNode.NextSibling;
end;
end; (*ProcessNode*)
begin
tree.Items.Clear;
XMLDoc.FileName := ChangeFileExt(ParamStr(0),'.XML');
XMLDoc.Active := True;

iNode := XMLDoc.DocumentElement.ChildNodes.First;

while iNode <> nil do begin
ProcessNode(iNode,nil);
iNode := iNode.NextSibling;
end;

XMLDoc.Active := False;
end;

procedure TForm1.btnLoadTreeClick(Sender: TObject);
var
ParentObj: TComponent;
XMLDoc: TXMLDocument;
begin
ParentObj := TComponent.Create(nil);
XMLDoc := TXMLDocument.Create(ParentObj);
XML2Tree(TreeView2, XMLDoc);
end;
(я для проверки сохранял из одного дерева, восстанавливал в другое... Из доп. информации сохраняется только строка Data, если у тебя есть еще что-то добавляй и в ProcessTreeItem, и в ProcessNode)...

Сообщение отредактировано: volvo -
 К началу страницы 
+ Ответить 
сообщение
Сообщение #30


Гость






Мне вот ещё что не понятно...
Как быть при записи/чтении в/из *.XML в случае, если TBPeriod имеет наследника TRange, который в свою очередь - TGroup, для TGroup есть наследник TUnderGroup, и для последнего - наследник TElement (причём объекты верхних ступенек иерархии имееют одни и те же поля, а TElement - в дополнии к ним ещё и новые..как учесть это??)
Объясните пожалуйста!
 К началу страницы 
+ Ответить 
сообщение
Сообщение #31


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(Гость @ 12.12.2008 19:29) *

Мне вот ещё что не понятно...
Как быть при записи/чтении в/из *.XML в случае, если TBPeriod имеет наследника TRange, который в свою очередь - TGroup, для TGroup есть наследник TUnderGroup, и для последнего - наследник TElement (причём объекты верхних ступенек иерархии имееют одни и те же поля, а TElement - в дополнии к ним ещё и новые..как учесть это??)
Объясните пожалуйста!


 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #32


Гость






Цитата
как учесть это??
Сохранять в XML вместе с данными еще и некоторый идентификатор, определяющий, объект какого именно типа надо будет создавать при восстановлении дерева... Скажем, при id="1", создаем TRange, если id="2", то TElement, и так далее...

Я бы сделал виртуальную функцию GetID: string, которая будет возвращать идентификатор для каждого типа объекта, тогда при записи в этот самый атрибут ID достаточно будет вызвать:
cNode.Attributes['ID'] := TBPeriod(tn.Data).GetID;
 К началу страницы 
+ Ответить 
сообщение
Сообщение #33


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(volvo @ 12.12.2008 19:50) *

Сохранять в XML вместе с данными еще и некоторый идентификатор...


//сохраняем...
if tn.Data <> nil then begin
cNode.Attributes['Feature'] := TPeriod(tn.Data).Feature;
cNode.Attributes['Count'] := TPeriod(tn.Data).Count;
cNode.Attributes['Id']:=1;
end
else cNode.Attributes['sData'] := '';


Например, так?
А для записи в XML наследников должен быть аналогичный код?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #34


Гость






Цитата
А для записи в XML наследников должен быть аналогичный код?
Ты ж сказала, что у тебя почти у всех классов одинаковые поля, значит изменения (т.е. добавление еще нескольких строк кода) будет только при сохранении TElement...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #35


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(volvo @ 12.12.2008 21:17) *

Ты ж сказала, что у тебя почти у всех классов одинаковые поля, значит изменения (т.е. добавление еще нескольких строк кода) будет только при сохранении TElement...

Да, так и будет..
Но я так и не поняла, где указывать эти несколько строк кода? В фрагменте из предыдущего поста?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #36


Гость






Ну, например, так:

    if tn.Data <> nil then begin
// значит, есть связанный с узлом объект... смотрим, какого он типа:
if TBPeriod(tn.Data) is TElement then begin
// здесь пишутся данные из класса TElement или его потомков
end
else begin
// здесь - изо всех остальных классов (до TElement в цепочке наследования)
end;
end
else cNode.Attributes['sData'] := '';

 К началу страницы 
+ Ответить 
сообщение
Сообщение #37


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Вот такой вопрос возник..
Если я хочу создать очередной узел (по нажатию соответствующей кнопки), то сначала в TreeView мне нужно выделить узел-родитель..Хочу сделать контроль возможности неверного выделения..
Скажите пожалуйста, как в этом случае сообщить о нарушении иерархии, если вместо предполагаемого родительского узла выделен узел того же уровня, что и новый или выделен узел, стоящий выше предполагаемого родительского?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #38


Гость






Цитата
как в этом случае сообщить о нарушении иерархии, если вместо предполагаемого родительского узла выделен узел того же уровня, что и новый
Где и как задается уровень НОВОГО узла? В предыдущей версии твоей программы новый узел добавлялся как дочерний к любому выделенному... Что теперь изменилось? Есть какие-то ограничения?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #39


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(volvo @ 16.12.2008 21:54) *

Есть какие-то ограничения?

ТОлько по смыслу)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #40


Гость






Ну, если дерево будет именно таким, как было сказано в самом первом посте, то с этим проблем нет, можно в конце концов выделять римские числа в заголовках узлов и проверять, подходит ли потомок к выбранному предку... А вот если я в группу "Неметаллы" захочу внести Селен и Теллур - ты сама, не заглядывая в таблицу вряд ли сможешь определить (по смыслу) ошибся ли я, и какой именно элемент не подходит для данной группы. Так что только по смыслу здесь не пойдет. Нужна какая-то доп. информация.
 К началу страницы 
+ Ответить 

3 страниц V < 1 2 3 >
 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 27.10.2020 22:33
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name