Delphi ttreeview пример создания дерева

DelphiComponent.ru — бесплатно видеоуроки по Delphi, статьи, исходники

Теперь нужно указать у нашего дерева в свойстве images установленный набор картинок. После этого можно переходить к программированию.

По нажатии кнопки Добавить мы должны добавлять в дерево новый элемент. Для этого будем использовать код, представленный в листинге:

procedure TTreeViewForm.AddButtonclick(Sender: TObject) ;

if not InputQuery( ‘ Ввод имени’, ‘Введите заголовок элемента’,CaptionStr) then exit;

NewNode: =TreeView1.Items. Add (TreeView1. Selected, CaptionStr) ;

if NewNode.Parentonil then NewNode.ImageIndex:=1;

Здесь мы объявили две переменные:

  • CaptionStr — типа строка string;
  • NewNode — типа TTreeNode (тип TTreeNode — это тип отдельного элемента дерева).

В первой строке кода мы обнуляем строку CaptionStr. Эта строка в будущем

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

if not InputQuery(‘Ввод имени’, ‘Введите заголовок элемента’, CaptionStr) then exit;

Дерево элементов (TTreeViert) в Delphi

Здесь выполняется функция InputQuery, которая используется для вывода на экран окна ввода. У этой функции есть три параметра.

  • Заголовок окна ввода.
  • Текст-пояснение, который подсказывает пользователю, что ему надо вводить.
  • Строковая переменная, в которой мы передаем значение по умолчанию и полу­чаем результат ввода.

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

На рис. вы можете увидеть это окно ввода.

Если окно было закрыто не кнопкой ОК, то происходит выход из процедуры. Об этом говорит фрагмент кода:

 if not InputQuery(. ) then exit;

Следующая строка кода добавляет новый элемент в наше дерево:

NewNode: =TreeView1. Items.Add(TreeViewl. Selected, CaptionStr);

У компонента Treeviewi есть свойство items, в котором хранятся все элементы дерева. Это свойство имеет объектный тип TTreeNodes. Чтобы добавить туда новый элемент, нужно вызвать метод Add объекта items. Получается, что в объекте Treeview1 есть еще один объект— items, в котором хранятся все элементы. Мы уже сталкивались с такими случаями, когда внутри одного объекта был другой объект. У метода Add есть два параметра:

  • элемент, к которому надо добавить новый (здесь мы передаем выделенный эле­мент Treeview1.Selected);
  • заголовок нового элемента.

Результат выполнения этого метода— указатель на новый элемент. Этот ре­зультат мы сохраняем в переменной NewNode. Теперь можно изменять и другие зна­чения этого элемента. Например, как в следующем коде изменяется картинка:

Читайте также:  Какие черви едят дерево

if NewNode. Par en tonil then NewNode.Imageindex:=1;

Здесь идет проверка, если свойство Parent нашего дерева не равно нулю (т. е. компонент не является верхним в дереве), то изменить значение imageindex соз­данного нами элемента на 1 (по умолчанию это значение 0).

Для события, вызываемого нажатием кнопки Добавить элемент, напишем код, показанный в листинге:

var CaptionStr:String; NewNode:TTreeNode;

if not InputQuery(‘Ввод имени подэлемента’, ‘Введите заголовок подэлементаCaptionStr) then exit;

NewNode: =TreeViewl. Items.AddChild(TreeViewl. Selected, CaptionStr) ;

if NewNode. Par en tonil then NewNode.Imageindex: =1 ;

Здесь код практически тот же, что и для кнопки Добавить. Единственная раз­ница в том, что при добавлении нового элемента используется метод Addchiid. От­личие этого метода от просто Add заключается в том, что он добавляет дочерний элемент. Например, если вы выделили в списке какой-то элемент и передали его в качестве первого параметра в Addchiid, то новый элемент будет как бы подчи­няться выделенному. При использовании метода Add новый элемент будет нахо­диться на одном уровне дерева с переданным в качестве первого параметра. Теперь напишем код для кнопки Удалить:

if TreeViewl .Selectedonil then TreeViewl.Items.Delete(TreeViewl.Selected);

Здесь нужно удалить выделенный элемент, поэтому сначала мы проверяем, есть ли вообще выделенный элемент в дереве: if TreeViewl.Selectedonil then

Если такой элемент есть, то выполнится следующий код:

TreeViewl.Items.Delete(TreeViewl.Selected);

Здесь используется метод Delete объекта items, чтобы удалить элемент дерева. В качестве параметра надо передать элемент, который мы хотим удалить (мы пере­даем выделенный TreeViewl.Selected).

Для кнопки Изменить заголовок мы напишем код листинга:

procedure TTreeViewForm.Edi tButtonclick(Sender: TObject);

var CaptionStr:String; begin CaptionStr:=»;

if not InputQuery(‘Ввод имени’,’Введите заголовок элемента’,CaptionStr) then exit;

Здесь снова вызывается окно InputQuery, чтобы пользователь смог ввести новое имя для выделенного элемента. Теперь, чтобы изменить имя, надо изменить свой­ство Text ДЛЯ выделенного элемента:

TreeView1 .Selected.Text.

Давайте сделаем возможность сохранения и загрузки данных в наше дерево. Для этого создайте обработчик события Onciose и напишите в нем следующее:

procedure TTreeViewForm. FormClose (Sender: TObject; var Action: TCloseAction);

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

Читайте также:  Войлочная вишня высота дерева

ExtractFilePath(Application.ExeName)+’tree.dat’

Application. ExeName — указывает на имя запущенного файла. ExtractFilePath— извлекает путь к файлу из указанного в качестве параметра пути К файлу. Получается, ЧТО ВЫЗОВ ExtractFilePath (Application. ExeName) вернет путь к папке, откуда была запущена программа. Остается только к этому пути при­бавить имя файла (у нас это ‘tree.dat’) и можно быть уверенным, что файл обяза­тельно будет находиться там же, где и запускаемый файл.

Теперь нужно загрузить сохраненные данные. Для этого по событию Onshow на­пишем следующий код:

procedure TTreeViewForm.FormShow(Sender: TObject);

begin if FileExists(ExtractFilePath(Application.ExeName) +1 tree.dat’) then TreeViewl.LoadFromFile(ExtractFilePath(Application.ExeName)+ ‘tree.dat’);

Здесь сначала проверяется с помощью вызова функции FileExists существова­ние файла. Этой функции нужно передать полное имя файла, и если он существует, то функция вернет true, иначе false.

Если файл существует, то можно его загрузить с помощью вызова метода LoadFromFile.

Обязательно проверяйте файл на существование. Если его нет или кто-то его удалил, а вы попытаетесь загрузить данные из несуществующего файла, произой­дет ошибка.

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

Итак, чтобы восстановить состояние картинок после загрузки данных из файла, надо скорректировать обработчик события Onshow следующим образом:

if FileExists(ExtractFilePath(Application.ExeName)+’tree.dat’) then

TreeViewl. LoadFromFile (ExtractFilePath (Application. ExeName) + ‘tree.dat’);

for i:=0 to TreeViewl.Iterns.Count-1 do

if TreeViewl.Items.Parent=nil then TreeViewl.Iterns.Imageindex:= 0 else TreeViewl.Iterns.Imageindex:=1;

Здесь сначала происходит загрузка данных из файла, а потом запускается цикл, в котором перебираются все элементы дерева. В цикле мы делаем проверку, если у текущего элемента свойство Parent равно nil, значит, у элемента нет родитель­ского элемента и он корневой, поэтому устанавливаем нулевую картинку. Если свойство не равно нулю, то элемент дочерний, и мы устанавливаем ему картинку с номером 1.

Вот и все. Вот таким простым способом мы восстанавливаем картинки элемен­тов, потому что они не сохраняются в файле.

Читайте также:  Выращивание бонсай дерево уход

Источник

Delphi. Иерархические данные. DBTreeView своими руками. Просмотр, добавление, редактирование, удаление узлов.

Встала задача построить дерево, связанное с базой данных, поддерживающее отображение иерархической структуры базы данных – какой-то конкретной иерархической таблицы. Например, отделы и сотрудники, содержащиеся в одной таблице – с колонкой idParent. Также нужны операции вставки новой записи в базу и в дерево и каскадное удаление – при удалении узла – удаляются все его дети. Готовых компонентов практически нет – из них ehLib и DevExpress, но это следующий шаг моего развития. В порядке тренировки решил попробовать решить задачу своими силами. В книге Дмитрия Осипова про базы данных. в принципе почти всё расписано – как и что нужно сделать, я повторил его пример, но нашёл там одну ошибку из за которой у меня выскакивало сообщение Invalid Pointer Operation, поправив которую – я получил то, что хотел. Вот что у меня получилось.

1

7

2

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

Подключение по FireDAC, БД MySQL.

Начнем!

Начать предлагаю с базы данных,в MySQL WorkBench я создал всего 1 таблицу, в принципе, для примера её вполне достаточно.

3

После создания базы из модели у меня получилось следующее. Базу желательно пока оставить пустой, это на картинке она у меня спустя некоторое время после создания. Это связано с алгоритмом сбора записей из базы, который мы опишем далее. Но если кратко, суть в том, что для правильной работы алгоритма все дети своих родителей должны быть с большим id нежели у родителя, если нарушить этот порядок в ручную – алгоритм будет работать некорректно. Но если заводить всё из интерфейса, то этот порядок будет соблюдаться автоматически, так как невозможно добавить ребенка без создания родителя.

4

Создание интерфейса

Создадим приложение VCL и добавим на него следующие элементы

5

Кнопка Selected здесь совершенно случайно, можете её не добавлять. Просто мне было лениво её убирать))) Я экспериментировал с установкой фокуса. Весь основной код по созданию подключения, алгоритмам добавления, редактирования, удаления узлов я перенес в отдельный датамодуль.

6

Вот какой код у нас в компонентах FDQuery

Источник

Оцените статью