powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Treeview и удобный способ определения узлов?
44 сообщений из 44, показаны все 2 страниц
Treeview и удобный способ определения узлов?
    #39814696
Сразу прошу не пинать, не программист. Так же уверен что в "гугле" на это уже сто раз давался ответ (да даже тут 900 тем находит по запросу treeview). Но как-то мозг кипит от чтения не того, что нужно.

Вопрос простой - как удобнее всего можно однозначно определять узел в Treeview, как при выделении пользователем, так и для выставлении курсором (или родителем).
Есть ли способ обращаться к узлу (например для добавления "листов") по индексам (как к массиву), ну например (21,4,100500) - где 21 индекс первого уровня, 4 - второго уровня у родителя "21", ну а 100500 - третьего у родителя "4". И обратно - вывести информацию об выделенном пользователем узле в указанном выше виде (можно и руками самому написать, но может что уже есть).

Насколько я понимаю TreeView1.Items ведет учет узлов просто по порядку без учета уровня и прочего, то есть для корректного обращения надо постоянно вести учет всех предыдущих узлов, что при динамическом создании всяких веток и листов как-то неудобно и выглядит костылем.

Ну и может подскажите по общей задаче. Делают такое классическое меню настроек как в большинстве программ, где щелкая по дереву настроек выпадают нужные настройки для редактирования, но(!), файл настроек представляет из себя несколько больших текстовых файлов, разбитых на разделы, которые ещё и постоянно редактируются в плане количества и вида настроек, потому все нужные элементы создаю динамически подгружая из файлов (при том элементы потом будут разные, и чекбоксы всякие, и даже картинки разные), потому сколько элементов в каждом узле и глубину я не знаю.

Картинки чисто для примера, не обращайте внимание на содержание, только на формат

...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39814698
Естественно через TreeView1.Items и пересчет узлов могу всё реализовать, но есть чувство, что это не правильно и есть более грамотные способы.
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39814702
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У узла есть свойство Data. Там можно хранить указатели на свои данные
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39814711
_Vasilisk_У узла есть свойство Data. Там можно хранить указатели на свои данные
Хм. Спасибо. Изучу. Вроде и видел, но как-то не подумал. Через Data можно задавать Node, или всё таки надо будет поиск по всем Data производить?
Ещё раз спасибо, пошел искать информацию.
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39814712
Фотография krapotkin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
лучше расскажите что за задача
зачем вам бежать по всем Node ?
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39814713
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ИгоревичЧерез Data можно задавать Node
Если нужен серфинг по "детям", то у каждого узла Items[i] = TTreeNоde, есть еще свойства HasChildren, Item и т.д.
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39814717
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ИгоревичЧерез Data можно задавать Node, или всё таки надо будет поиск по всем Data производить?Не понял вопроса.

Какая у вас задача? По узлу сопоставить ему некоторые данные? Или найти узел по каким-то признакам?
Андрей Игоревичну например (21,4,100500) - где 21 индекс первого уровня, 4 - второго уровня у родителя "21", ну а 100500 - третьего у родителя "4".
Код: pascal
1.
TreeView1.Items[21][4][100500]
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39814718
Фотография Gator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ИгоревичЧерез Data можно задавать Node, или всё таки надо будет поиск по всем Data производить?В Data можно хранить хоть чёрта лысого. Тут главное обеспечить наличие и соответствие типа этого лысого чёрта.
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39814764
krapotkinлучше расскажите что за задача
зачем вам бежать по всем Node ?
Ну я больше не "бежать по всем" имел в виду, а обратиться к любому нужному в любой момент напрямую.

wadmanАндрей ИгоревичЧерез Data можно задавать Node
Если нужен серфинг по "детям", то у каждого узла Items[i] = TTreeNоde, есть еще свойства HasChildren, Item и т.д.
Спасибо, изучу.


_Vasilisk_Андрей ИгоревичЧерез Data можно задавать Node, или всё таки надо будет поиск по всем Data производить?Не понял вопроса.

Какая у вас задача? По узлу сопоставить ему некоторые данные? Или найти узел по каким-то признакам?

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

_Vasilisk_
Код: pascal
1.
TreeView1.Items[21][4][100500]


Отлично, практически то, что я и хотел, единственно, как я понимаю, таким образом я могу обращаться только к элементам одного уровня (в зависимости от количества скобок). Попытка подставить "-1" и "nil", увы, не помогла.

GatorАндрей ИгоревичЧерез Data можно задавать Node, или всё таки надо будет поиск по всем Data производить?В Data можно хранить хоть чёрта лысого. Тут главное обеспечить наличие и соответствие типа этого лысого чёрта.

А запись с кучей многомерных динамических массивов на пол гигабайта съест? Или таким лучше всё таки не заниматься :)?
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39814771
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревичтаким образом я могу обращаться только к элементам одного уровня (в зависимости от количества скобок). Попытка подставить "-1" и "nil", увы, не помогла.Наоборот, это обращение к элементам трех разных уровней
Андрей Игоревичдалее при выделении каждого узла выполнять определенные действияЗаносите идентификатор действий в Data. Обращаетесь к ней при выделении узла из события TreeView.OnChange
Андрей Игоревичтак же необходимо в любой момент выделить нужный узел/лист программно с выполнением привязанных к нему действий.
Код: pascal
1.
2.
Node.Selected := True;
TreeView1.OnChange(TreeView1, Node);
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39814776
Фотография Gator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ИгоревичА запись с кучей многомерных динамических массивов на пол гигабайта съест? Или таким лучше всё таки не заниматься :)?В Data сидит указать, узлу начхать, на что он указывает.
Кроме того, там можно хранить битовую маску.
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39814785
delphinotes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
автор, посмотри в сторону VirtualTreeView
компонент другой (бесплатный), но более гибкий и мощнее, с кучей примеров... возможно он больше подойдёт
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39814792
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич,

не знаю, то ли вы ищете.
TCustomTreeView.Selected - указывает на выделенный узел.
TTreeNode.Index - индекс (номер) данного узла в списке детей его родителя.
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39814803
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сдается мне, что автор придумал кривое решение задачи и мы должны помочь с реализацией вместо того, чтобы узнать саму задачу первым делом.
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39814814
Gerasimenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39814821
Более менее вник в то, что мне написали и понял, что все примерно одно и тоже и предлагают :), но в большинстве не совсем то, что я спрашивал (ну отчасти). Про TreeView.Selected.Index, TreeView.Selected.AbsoluteIndex, TreeView1.OnChange и прочее подобно я естественно освоил сразу ибо есть во всяких нубомануалах в интернете.

Задам вопрос иначе с примером понагляднее (сформирован рандомно).


Задача 1: Как наиболее простым способом программно (не выделением пользователем) одной общей процедурой на все, ну например, добавить несколько "узлов" в "Ещё какие-нибудь параметры 4 2 0", а потом добавить ещё несколько в "Глобальные параметры 4", а потом ещё куда-нибудь. Ну суть, думаю, ясна.
Через
Код: pascal
1.
TreeView1.Items[21][4][100500]

не понятно как выбрать узел второго уровня (1го если от 0) и так же не понятно как он работает с нулевым уровнем, так как, например
Код: pascal
1.
TreeView1.Items[5]

выделит не "Глобальные параметры 5", а "Локальные параметры 0 1" (ну по абсолютному индексу).
Можно обыграть условиями, но тоже как-то не очень.

Задача 2 (в принципе эта задача решается через Data, но вдруг ещё чего подскажите): Как при выделении пользователем любого узла получить привязанные к нему параметры однозначно и удобно его определяющие, наиболее удобно - индексы как те что после текста.
Тут всё можно полностью через Data реализовать, думаю можно даже сами данные тогда в Data сохранять, а не в отдельных масивах, так что особо можно не мусолить, хотя если есть иные способы...
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39814823
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ИгоревичЗадача 1: Как наиболее простым способом программно (не выделением пользователем) одной общей процедурой на все, ну например, добавить несколько "узлов" в "Ещё какие-нибудь параметры 4 2 0", а потом добавить ещё несколько в "Глобальные параметры 4", а потом ещё куда-нибудь. Ну суть, думаю, ясна.


Код: pascal
1.
2.
3.
4.
5.
6.
Node := FindNode(Имя или номер); // функция которая отыщет нужный узел по параметру
if Node <> nil then begin
  TreeView.AddNode(Node,'Новый узел 1');
  TreeView.AddNode(Node,'Новый узел 2');
  TreeView.AddNode(Node,'Новый узел 3');
end;



не понятно как выбрать узел второго уровня (1го если от 0) и так же не понятно как он работает с нулевым уровнем, так как, например
Код: pascal
1.
TreeView1.Items[5]

выделит не "Глобальные параметры 5", а "Локальные параметры 0 1" (ну по абсолютному индексу).


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
function GetNode(TV: TTreeView; Index: integer): TTreeNode;
begin
  Result := TV.Items.GetFirstNode;
  while (Result <> nil) and (Index > 0) do begin
    Result := Result.getNextSibling;
    Dec(Index);
  end;
end;

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  GetNode(TreeView1,5).Selected := true;
end;



Задача 2 (в принципе эта задача решается через Data, но вдруг ещё чего подскажите): Как при выделении пользователем любого узла получить привязанные к нему параметры однозначно и удобно его определяющие, наиболее удобно - индексы как те что после текста.
Тут всё можно полностью через Data реализовать, думаю можно даже сами данные тогда в Data сохранять, а не в отдельных масивах, так что особо можно не мусолить, хотя если есть иные способы...
Откуда берутся данные ? Если из Dataset то достаточно в Data загнать уникальный номер строки.
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39815193
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич,

"задача 1" это не задача, а некое её решение. Задача - это то, что "задача" должна решать.
При каких условиях "задача" возникает? В БД появились данные? Узел развернут пользователем? Какое-то иное внешнее событие?
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39816355
DimaBrАндрей ИгоревичЗадача 1: Как наиболее простым способом программно (не выделением пользователем) одной общей процедурой на все, ну например, добавить несколько "узлов" в "Ещё какие-нибудь параметры 4 2 0", а потом добавить ещё несколько в "Глобальные параметры 4", а потом ещё куда-нибудь. Ну суть, думаю, ясна.

...



Спасибо, вроде то, что нужно, ну точнее буду использовать это :).

DimaBrЗадача 2 (в принципе эта задача решается через Data, но вдруг ещё чего подскажите): Как при выделении пользователем любого узла получить привязанные к нему параметры однозначно и удобно его определяющие, наиболее удобно - индексы как те что после текста.
Тут всё можно полностью через Data реализовать, думаю можно даже сами данные тогда в Data сохранять, а не в отдельных масивах, так что особо можно не мусолить, хотя если есть иные способы...
Откуда берутся данные ? Если из Dataset то достаточно в Data загнать уникальный номер строки.
Данные берутся из текстовых файлов всевозможных форматов (там и списки настроек, и массивы всяких размерностей, форм и цветов, и просто текст).
Пользователь просто щелкает слева по дереву (в дереве отображаются имена файлов, разделы файлов, подразделы) и видит нужную информацию (ну в общем, каждая вторая инженерная/научная расчетная программа имеет похожий интерфейс).
Информацию я рисую в зависимости от названия файла (и, естественно, содержания) динамически генерируя на экране (на скролбаре) всякие разные менюшки, эдиты, лейблы, имейджи и прочее.


wadmanАндрей Игоревич,

"задача 1" это не задача, а некое её решение. Задача - это то, что "задача" должна решать.
При каких условиях "задача" возникает? В БД появились данные? Узел развернут пользователем? Какое-то иное внешнее событие?
Ну основное - в дереве показаны файлы настроек и разделы из них, пользователь подгрузил новый файл, надо добавить его и его разделы в дерево.
Но в принципе я пока решил отказаться от такого и просто генерирую всё дерево заново при обновлении, так проще.


Хотел тут куски кода привести, но подумал "не, гадостей наговорят, нафиг" :).
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39816461
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вы загружаете кучу файлов, которые затем отображаете в дереве.
Вам нужно сопоставить узел с файлом.
1. Сопоставить по имени.
2. Загрузить все файлы в список, а в узел дерева (Data) записать номер по списку
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39816638
DimaBrВы загружаете кучу файлов, которые затем отображаете в дереве.
Вам нужно сопоставить узел с файлом.
1. Сопоставить по имени.
2. Загрузить все файлы в список, а в узел дерева (Data) записать номер по списку
Сейчас реализовал по имени.

Есть ещё несколько вопросов которые с нахрапу не могу в интернете найти, точнее решения разные есть, но не всегда уверен, что они корректны или подходят мне.
1. Как всё-таки корректно работать с Data.
Пока я для пример сделал так:




Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
 

node.Data:=Pointer(FilePaths[_i]);



   if node.Data <> nil then 
    begin
        label2.Caption:=string(node.Data);
        Label2.Left:=ScrollBox1.Left+round(ScrollBox1.Width/2)-round(Label2.Width/2);
    end else
    if Node.Parent.Data <> nil then
    begin
        label2.Caption:=string(node.Parent.Data);
        Label2.Left:=ScrollBox1.Left+round(ScrollBox1.Width/2)-round(Label2.Width/2);
    end;
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39816646
Андрей Игоревич,

Так, я что-то нажал и оно отправилось. Как редактировать или удалять тут сообщения я не нашел, будем считать что того сообщения небыло :)

DimaBrВы загружаете кучу файлов, которые затем отображаете в дереве.
Вам нужно сопоставить узел с файлом.
1. Сопоставить по имени.
2. Загрузить все файлы в список, а в узел дерева (Data) записать номер по списку
Сейчас реализовал по имени.

Есть ещё несколько вопросов которые с нахрапу не могу в интернете найти, точнее решения разные есть, но не всегда уверен, что они корректны или подходят мне.

1. Как всё-таки корректно работать с Data?
Тут я сделал вывод адреса файла в лейбел при клике по любому узлу. Правильно ли делаю, или я вообще всё не так делаю?
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
...
node.Data:=Pointer(FilePaths[_i]);
...

   if node.Data <> nil then 
    begin
        label2.Caption:=string(node.Data);
    end else
    if Node.Parent.Data <> nil then
    begin
        label2.Caption:=string(node.Parent.Data);
    end;


2. Как пробежаться только по нулевому уровню дерева? Можно пробежаться по всему проверяя индекс, но как-то не спортивно...

Блин, пока писал, забыл что ещё спросить хотел...
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39818673
Вот пришел я к индексам через data к узлам и неожиданно возник вопрос:
а как удобнее всего индексы то запоминать.

Допустим у меня есть индексы узлов [1,0,0,0] [100500,0,0,0], для коневых, всякие [3,5,10,0] для для более глубоких узлов, как их сохранить то? Может есть общепринятый формат?
Можно сохранить строкой - 3,5,10,0.
Можно сохранить записью -
Index = record;
lvl1: byte;
lvl2: byte;
lvl3: byte;
lvl4: byte;
End;

Может ещё как можно?
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39818779
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Зачем вообще хранить длинные индексы ?

Хотите хранить в узлах много дополнительных данных, заведите новый тип узла
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
TMyNode = class(TTreeNode)
  lvl1: byte;
  lvl2: byte;
  lvl3: byte;
  lvl4: byte;
end;

// создание узла дерева
var N: TMyNode;
begin
  N := TMyNode.Create;
  N.lvl1 := <данные>;
  TreeView1.AddNode(N, Parent, 'Text', nil, naAddChild);
end;
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39818838
DimaBrЗачем вообще хранить длинные индексы ?


Потому что так гораздо удобнее соотносить узел с конкретными данными (данных много и они разнородны, в узлы их засовывать сложно, да и не нужно).

DimaBr
Хотите хранить в узлах много дополнительных данных, заведите новый тип узла

Много не надо, только индексы...
Блин, а выше тут писали, что и Data хватит :). Теперь вот уже свой узел. Так дойдет что проще свой компонент написать будет (шутка, если что :)).

При том и с Data что-то вообще не получается.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
       
 TIndex =record
  lv1:byte;
  lv2:byte;
  lv3:byte;
  lv4:byte;
 end;
     
var
  Indx:array [0..1000] of TIndex;
  lv1,lv2,lv3,lv4:byte
_IndexTree:integer;
...
Begin
...
 lv1:=0; lv2:=0; lv3:=0; lv4:=0;
...


for .. to .. do
...
   inc(_IndexTree);                                  
 {Inc(lv1);} Inc(lv2); lv3:=0; lv4:=0;               
  Indx[IndexTree].lv1:=lv1; 
  Indx[IndexTree].lv2:=lv2;  
  Indx[IndexTree].lv3:=lv3; 
  Indx[IndexTree].lv4:=lv4;
  node.data:=Pointer(Indx[IndexTree]);

...
end



Вылетает с ошибкой на ошибку чтения из памяти, при том вылетает при завершении процедуры в которую вложен, индексы lv - даже 100 не не превышают. Да хоть нули - вылетает (но не всегда...).
При замене на
Код: pascal
1.
2.
3.
4.
5.
6.
 TIndex =record
  lv1:ineger;
  lv2:ineger;
  lv3:ineger;
  lv4:ineger;
 end;


вообще пишет "Invalid typecast".

В общем что-то как-то не могу, разобраться, в хелпе такой себе пример для понимания.

Если не смогу понять, то попробую как вы предлагаете через свой узел
DimaBr
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
TMyNode = class(TTreeNode)
  lvl1: byte;
  lvl2: byte;
  lvl3: byte;
  lvl4: byte;
end;

// создание узла дерева
var N: TMyNode;
begin
  N := TMyNode.Create;
  N.lvl1 := <данные>;
  TreeView1.AddNode(N, Parent, 'Text', nil, naAddChild);
end;



А может вообще забью, в принципе через поиск всё работает, но уж больно мне не нравится код, где куча всяких циклов, условий и поисков, неудобный и ощибкоопасный.
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39818857
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это разные переменные
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
_IndexTree:integer;
...
Begin
...
 lv1:=0; lv2:=0; lv3:=0; lv4:=0;
...


for .. to .. do
...
   inc(_IndexTree);                                  
 {Inc(lv1);} Inc(lv2); lv3:=0; lv4:=0;               
  Indx[IndexTree].lv1:=lv1; 
  Indx[IndexTree].lv2:=lv2;  
  Indx[IndexTree].lv3:=lv3; 
  Indx[IndexTree].lv4:=lv4;
  node.data:=Pointer(Indx[IndexTree]);

...
end
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39818865
DimaBrЭто разные переменные
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
_IndexTree:integer;
...
Begin
...
 lv1:=0; lv2:=0; lv3:=0; lv4:=0;
...


for .. to .. do
...
   inc(_IndexTree);                                  
 {Inc(lv1);} Inc(lv2); lv3:=0; lv4:=0;               
  Indx[IndexTree].lv1:=lv1; 
  Indx[IndexTree].lv2:=lv2;  
  Indx[IndexTree].lv3:=lv3; 
  Indx[IndexTree].lv4:=lv4;
  node.data:=Pointer(Indx[IndexTree]);

...
end


Это я коряво вставил на форум просто, хотел убрать все подчеркивания, чтоб получше читалось (я вообще переменные которые потенциально могут совпасть с каким-нибудь оператором начинаю с "_"), но где-то забыл убрать :). Они одинаковые там :). (но на всякий случай проверил)

Вроде поправил.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
       
 TIndex =record
  lv1:byte;
  lv2:byte;
  lv3:byte;
  lv4:byte;
 end;
     
var
  Indx:array [0..1000] of TIndex;
  lv1,lv2,lv3,lv4:byte
  IndexTree:integer;
...
Begin
...
 lv1:=0; lv2:=0; lv3:=0; lv4:=0;
...


for .. to .. do
...
   inc(IndexTree);                                  
 {Inc(lv1);} Inc(lv2); lv3:=0; lv4:=0;               
  Indx[IndexTree].lv1:=lv1; 
  Indx[IndexTree].lv2:=lv2;  
  Indx[IndexTree].lv3:=lv3; 
  Indx[IndexTree].lv4:=lv4;
  node.data:=Pointer(Indx[IndexTree]);

...
end
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39818872
goldmi45
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич,

У TTreeNode есть ещё Parent - ссылка на родительскую ноду. Т.е. зная выделенную ноду (TreeView.Selected), можно получить Parent.
В Data у ноды можно хранить ссылку на элемент в списке, какие настройки нужно отображать при выделении этого узла. Т.е. задача стоит не в том, как определить, какой узел выделен, а в одновременном формировании дерева и списка с настройками и привязки узлов дерева к списку с настройками.
Вы читаете файл настроек, создаёте список этих файлов и строите узел дерева в Data указав ссылку на идентификатор файла в списке.

Ваши сообщения очень сумбурные и малопонятные. Древовидная структура берётся из структуры каталогов или из файла? Можно ли отобразить настройки, скажем, для "Общие параметры ТВС 0-6" (узел второго уровня из стартового сообщения), или можно отобразить настройки только для конечных узлов?
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39818874
goldmi45
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
       
 TIndex =record
  lv1:byte;
  lv2:byte;
  lv3:byte;
  lv4:byte;
 end;
     
var
  Indx:array [0..1000] of TIndex;
  lv1,lv2,lv3,lv4:byte
  IndexTree:integer;
...
Begin
...
 lv1:=0; lv2:=0; lv3:=0; lv4:=0;
...


for .. to .. do
...
   inc(IndexTree);                                  
 {Inc(lv1);} Inc(lv2); lv3:=0; lv4:=0;               
  Indx[IndexTree].lv1:=lv1; 
  Indx[IndexTree].lv2:=lv2;  
  Indx[IndexTree].lv3:=lv3; 
  Indx[IndexTree].lv4:=lv4;
  node.data:=Pointer(Indx[IndexTree]);

...
end


Подумайте, что будет, вложенность будет больше, чем 4 уровня? Будете переписывать код, добавляя lvl5, lvl6 ... lvl10?
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39818887
goldmi45Андрей Игоревич,

У TTreeNode есть ещё Parent - ссылка на родительскую ноду. Т.е. зная выделенную ноду (TreeView.Selected), можно получить Parent.

Использую повсеместно.

goldmi45Андрей Игоревич,
В Data у ноды можно хранить ссылку на элемент в списке, какие настройки нужно отображать при выделении этого узла. Т.е. задача стоит не в том, как определить, какой узел выделен, а в одновременном формировании дерева и списка с настройками и привязки узлов дерева к списку с настройками.
Вы читаете файл настроек, создаёте список этих файлов и строите узел дерева в Data указав ссылку на идентификатор файла в списке.

Как я понял просто одномерный массив индексов, ну тоже вариант, надо обдумать. Изначально тоже о нем подумал, но решил, что массив с уровнями куда "читабельней" (уж больно я потом в своём коде начинаю путаться, потому стараюсь писать так, чтоб сразу понять что тут и к чему).

goldmi45Андрей Игоревич,
Ваши сообщения очень сумбурные и малопонятные. Древовидная структура берётся из структуры каталогов или из файла? Можно ли отобразить настройки, скажем, для "Общие параметры ТВС 0-6" (узел второго уровня из стартового сообщения), или можно отобразить настройки только для конечных узлов?
В том то и сложность задачи для меня, древовидная структура одновременно берется и из самих файлов (есть группы файлов одного плана) и из их содержимого, есть файлы где по 200+ настроек, разбитые на разделы. Есть вообще всякая геометрия, поля и прочее подобное, где изначально будет общая геометрия, а по мере раскрытия узлов всякие дополнительные параметры, на сколько уровней пока не продумывал. Отобразить можно как угодно и что угодно - главное что бы это было удобно и интуитивно понятно.
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39818891
goldmi45Андрей Игоревич
Подумайте, что будет, вложенность будет больше, чем 4 уровня? Будете переписывать код, добавляя lvl5, lvl6 ... lvl10?
Так вродеж тем и хороши записи, что добавив уровни не надо ничего переписывать. В общем надо подумать.
Сейчас у меня просто поиск по имени узла и имени родителя происходит, который сверяю с сохраненными данными и вывожу форму. Всё прекрасно работает, но мне не нравится, вообще нечитабильно.
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39818988
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вылетает с ошибкой на ошибку чтения из памяти, при том вылетает при завершении процедуры в которую вложен

Думаю что это происходит из-за
Код: pascal
1.
node.data:=Pointer(Indx[IndexTree]);



Попробуйте хранить так
Код: pascal
1.
node.data := Pointer(IndexTree);




Я так и не понимаю, что вы храните в
Код: pascal
1.
2.
3.
4.
5.
6.
 TIndex =record
  lv1:byte;
  lv2:byte;
  lv3:byte;
  lv4:byte;
 end;
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39819080
goldmi45
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревичgoldmi45пропущено...

Подумайте, что будет, вложенность будет больше, чем 4 уровня? Будете переписывать код, добавляя lvl5, lvl6 ... lvl10?
Так вродеж тем и хороши записи, что добавив уровни не надо ничего переписывать. В общем надо подумать.

Ошибаетесь. Необходимо будет в записи добавить ещё одну переменную, необходимо дописать поиск, вывод. Перекомпилить наконец. А это не всегда возможно (потеря исходников, например, может случиться).

Андрей ИгоревичСейчас у меня просто поиск по имени узла и имени родителя происходит, который сверяю с сохраненными данными и вывожу форму. Всё прекрасно работает, но мне не нравится, вообще нечитабильно.
При таком подходе - грабли слегка прикрыты сеном. Может ли случиться такая ситуация, когда будет два разных узла, у которых наименование их и их родителей совпадут? Если это не случится сегодня, может ли такой сценарий реализоваться в будущем?
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39819200
Beltar
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторКак всё-таки корректно работать с Data?

Просто преобразовывать тип.

Например.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
TNodeDescr=class
  F1:Integer;
  F2:Integer;
end;

Node.Data:=TNodeDescr.Create;

TNodeDescr(Node.Data).F1;



Я не очень понимаю, чем вас не устраивает простой перебор нодов?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
for i:=0 to TreeView.Items.Count-1 do
  begin
  if TNodeDescr(Items[i].Data).F1=Something then //Ну или любой критерий отбора, хоть функцию сложную напишите, например, можете по тексту узла искать.
    begin
    ShowMessage('Индекс узла равен '+IntToStr(i));
    Break;
    end;
  end;



Если у вас даже тыща-другая узлов, это все равно будет работать быстрее, чем вы сможете почувствовать.
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39819204
Beltar
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторесть файлы где по 200+ настроек, разбитые на разделы.

А вы загрузить это сможете? Задача как бы не совсем примитивная, я как-то делал аналог проги DelphiWorld с загрузкой и сохранением в бинарник своего формата, но там я как захотел, так и сделал, у меня просто с узлом хранилось число дочерных и все делалось через стек родительских узлов (деревья вообще любят стековые алгоритмы). А как у вас в файле всё это организовано.
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39819438
goldmi45Андрей Игоревичпропущено...

Так вродеж тем и хороши записи, что добавив уровни не надо ничего переписывать. В общем надо подумать.

Ошибаетесь. Необходимо будет в записи добавить ещё одну переменную, необходимо дописать поиск, вывод. Перекомпилить наконец. А это не всегда возможно (потеря исходников, например, может случиться).

Не, ну как бы любые корректировки подобного масштаба к чему-то подобному приведут, доживем - подумаем :)

Андрей Игоревичпропущено...

Андрей ИгоревичСейчас у меня просто поиск по имени узла и имени родителя происходит, который сверяю с сохраненными данными и вывожу форму. Всё прекрасно работает, но мне не нравится, вообще нечитабильно.
При таком подходе - грабли слегка прикрыты сеном. Может ли случиться такая ситуация, когда будет два разных узла, у которых наименование их и их родителей совпадут? Если это не случится сегодня, может ли такой сценарий реализоваться в будущем?
Могут, тоже одна из причин почему не очень нравится.


DimaBrВылетает с ошибкой на ошибку чтения из памяти, при том вылетает при завершении процедуры в которую вложен

Думаю что это происходит из-за
Код: pascal
1.
node.data:=Pointer(Indx[IndexTree]);


Логично :), после добавления этого кода и начало вылетать.



DimaBr
Попробуйте хранить так
Код: pascal
1.
node.data := Pointer(IndexTree);



Ну это ничем не будет отличатся от обычного индекса узла, что вызывает некоторые сложности к обращению к данным.


DimaBrЯ так и не понимаю, что вы храните в
Код: pascal
1.
2.
3.
4.
5.
6.
 TIndex =record
  lv1:byte;
  lv2:byte;
  lv3:byte;
  lv4:byte;
 end;


Индексы для узла. Суть в том, что я структурировал данные в виде записи так же, как они выглядят в дереве TreeNode, поэтому обращаться к конкретной ячейке памяти по таким индексам можно напрямую, без поисков и прочего.


BeltarавторКак всё-таки корректно работать с Data?

Просто преобразовывать тип.

Например.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
TNodeDescr=class
  F1:Integer;
  F2:Integer;
end;

Node.Data:=TNodeDescr.Create;

TNodeDescr(Node.Data).F1;


Ну это не особо отличается от "своего узла" с индексами предложенного выше :).


BeltarЯ не очень понимаю, чем вас не устраивает простой перебор нодов?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
for i:=0 to TreeView.Items.Count-1 do
  begin
  if TNodeDescr(Items[i].Data).F1=Something then //Ну или любой критерий отбора, хоть функцию сложную напишите, например, можете по тексту узла искать.
    begin
    ShowMessage('Индекс узла равен '+IntToStr(i));
    Break;
    end;
  end;



Если у вас даже тыща-другая узлов, это все равно будет работать быстрее, чем вы сможете почувствовать.
Ну пока так и работает, и даже быстро, просто из-за кучи мелких нюансов (разного формата данных из файлов) в коде возникает огромное количество условий, циклов проверок на всё подряд, при возникновении ошибки в которых у меня начинает кипеть мозг.

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



Beltarавторесть файлы где по 200+ настроек, разбитые на разделы.

А вы загрузить это сможете? Задача как бы не совсем примитивная, я как-то делал аналог проги DelphiWorld с загрузкой и сохранением в бинарник своего формата, но там я как захотел, так и сделал, у меня просто с узлом хранилось число дочерных и все делалось через стек родительских узлов (деревья вообще любят стековые алгоритмы). А как у вас в файле всё это организовано.
Смогем, и не такое грузили (не без помощи товарищей с этого форума), даже пол сотни гигабайт грузил :).
В данном случае объемы данных исчисляются от силы парой гигабайт, даже на 64 бита не придется переходить :).
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39819530
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Индексы для узла. Суть в том, что я структурировал данные в виде записи так же, как они выглядят в дереве TreeNode, поэтому обращаться к конкретной ячейке памяти по таким индексам можно напрямую, без поисков и прочего.

Кто мешает написать функцию обращения к узлам дерева по индексам ?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
function GetNode(TV: TTreeView; Index: array of integer): TTreeNode;
var i: integer;
begin
  Result := nil;
  if Length(Index) = 0 then Exit;
  Result := TV.Items.GetFirstNode;
  while (Result <> nil) and (Index[0] > 0) do begin
    Result := Result.getNextSibling;
    Dec(Index[0]);
  end;

  for i := 1 to High(Index) do
    if Result.Count < Index[i] then begin
      Result := nil;
      Exit;
    end
    else Result := Result.Item[Index[i]];
end;

procedure TForm1.FormCreate(Sender: TObject);
var i,j: integer;
    N,X: TTreeNode;
begin
  for i := 0 to 9 do begin
    N := TreeView1.Items.Add(nil,'Глобальные параметры ' + IntToStr(i));
    for j := 0 to 5 do begin
      X := TreeView1.Items.AddChild(N,'Локальные параметры ' + IntToStr(i)+'.'+IntToStr(j));
      TreeView1.Items.AddChild(X,'Дополнительные параметры ' + IntToStr(i)+'.'+IntToStr(j)+'.0');
      TreeView1.Items.AddChild(X,'Дополнительные параметры ' + IntToStr(i)+'.'+IntToStr(j)+'.1');
      TreeView1.Items.AddChild(X,'Дополнительные параметры ' + IntToStr(i)+'.'+IntToStr(j)+'.2');
    end;
  end;
  TreeView1.FullExpand;
end;

procedure TForm1.Button1Click(Sender: TObject);
var A: array of integer;
    S: string;
    i: integer;
    N: TTreeNode;
begin
  S := Edit1.Text;
  while S <> '' do begin
    i := Pos('.',S);
    if i = 0 then i := Length(A);
    SetLength(A,Length(A)+1);
    A[High(A)] := StrToInt(copy(S,1,i-1));
    Delete(S,1,i);
  end;
  N := GetNode(TreeView1,A);
  if N <> nil
    then Caption := N.Text
    else Caption := 'Не такого узла';
end;

...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39820065
DimaBrИндексы для узла. Суть в том, что я структурировал данные в виде записи так же, как они выглядят в дереве TreeNode, поэтому обращаться к конкретной ячейке памяти по таким индексам можно напрямую, без поисков и прочего.

Кто мешает написать функцию обращения к узлам дерева по индексам ?

Код: pascal
1.
....


Ничего не мешает, записать индексы в строку и потом брать их оттуда я подумал сразу, о чем и написал, когда спрашивал :). Просто я подумал, что есть более аккуратное решение. Только строку сохранять в Data (это работает без проблем), а не в название.
Наверно так и поступлю.
Но из вашего кода узнал для себя кучу новых способов работы с TreeViev, спасибо :).
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39820124
Фотография Gator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич> Ничего не мешает, записать индексы в строку и потом брать их оттуда я подумал...

В раздрызге спьяну?

В "название" (name) именно и надо писать название (в терминах предметной области, команды , маску чёрта лысого...) Строка слишком короткая, чтобы в неё индексы писать, и неудобно смотреть на такое.

А остальные атрибуты - в любую свою структуру. Вот адрес этой структуры и надо писать в Data (данные пользователя), маску флажков, адрес адреса.
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39820126
GatorАндрей Игоревич> Ничего не мешает, записать индексы в строку и потом брать их оттуда я подумал...

В раздрызге спьяну?

В "название" (name) именно и надо писать название (в терминах предметной области, команды , маску чёрта лысого...) Строка слишком короткая, чтобы в неё индексы писать, и неудобно смотреть на такое.

А остальные атрибуты - в любую свою структуру. Вот адрес этой структуры и надо писать в Data (данные пользователя), маску флажков, адрес адреса.
Ничего не понял, но ок :). Яж вроде писал, что индексы сохранять в строку, а строку уже в Data. Имя пусть именем и остается.
Как делать ссылки(адреса стуктуры) через Data понятия не имею.
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39820128
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ИгоревичЯж вроде писал, что индексы сохранять в строку, а строку уже в Data.
Зачем в Data хранить индексы ? Что вы этим с этим индексом хотите делать ?
Положение узла в дереве и так определяется без всяких Data.
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39820131
Фотография Gator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ИгоревичКак делать ссылки(адреса стуктуры) через Data понятия не имею.

в x32 системах Data = 4-м байтам и структура сидит по адресу в 4 байта.
Код: pascal
1.
2.
3.
  node.Data := Pointer(SomeObj);  
  node.Data := Pointer(SomeRec);  
  ny.Data := Pointer(DateToInt(iy, 0, 0));

на что похоже?
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39820132
Фотография Gator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DimaBrАндрей ИгоревичЯж вроде писал, что индексы сохранять в строку, а строку уже в Data.
Зачем в Data хранить индексы ? Что вы этим с этим индексом хотите делать ?
Положение узла в дереве и так определяется без всяких Data.
Индекс индексу рознь и люпус ест :)
Как быть с сиквельными xml или составными индексами, IP/MAC адресами?
...
Рейтинг: 0 / 0
Treeview и удобный способ определения узлов?
    #39820133
Фотография Gator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А ещё у контролов есть Tag. Через него тоже можно связывать всяко разно
...
Рейтинг: 0 / 0
44 сообщений из 44, показаны все 2 страниц
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Treeview и удобный способ определения узлов?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]