Delphi. Панель Win32. Компонент TreeView. Часть 4

Пиктограммы около узлов дерева.

Как правило, около узлов дерева бывают размещены одна или две картинки — пиктограммы. Например:

Эти пиктограммы могут принимать два состояния: в зависимости от того, выделен узел или нет.

Рассмотрим последовательность шагов назначения пиктограммы узлу.

Во-первых, сами пиктограммы должны быть созданы. Это могут быть небольшие изображения типа «.bmp», или иконки типа «.ico».

После того, как такие изображения созданы, они должны быть загружены в компоненте «ImageList» (если размер картинки типа «.bmp» больше допестимого в «ImageList», то при загрузке задаётся вопрос, надо ли разбить картинку на ряд маленьких картинок. На этот вопрос следует ответить «нет» и тогда картинка автоматически сожмётся до нужного размера, после чего загрузится в компонент).

Например:

Далее надо привязать компонент «ImageList1» к компоненту «TreeView1».

Это делается при помощи свойства «Images» путём выбора из выпадающего списка (если на форме размещено несколько компонентов «ImageList1», то все они будут отображены в списке. Мы выбираем нужный нам).

Чтобы изображение было размещено около соответствующего узла, необходимо в редакторе узлов указать соответствующий индекс.

Например, пусть мы в редакторе узлов построили дерево:

В поле«Image Index», будет указан индекс картинки, которая будет отображаться около узла. В нашем случае это будет:

то есть «Image Index=2»

Аналогично, в поле«Selected Index» будет указан индекс картинки, которая будет отображаться ококло выделенного (выбранного) узла. Для начала назначим выделенному узлу ту же картинку, то есть «Selected Index=2».

Второй картинки около узла «узел_0» в нашем примере не будет, поэтому «State Index» равен «-1».

Конечным узлам дерева (листьям — это узлы «узел_11», «узел_121», «узел_13» и «узел_1») назначаем картинку:

то есть для этих узлов «Image Index=4» и «Selected Index=4».

В итоге после запуска программы будем иметь:

то есть для этих узлов «Image Index=4» и «Selected Index=4».

Теперь поставим следующую задачу:

1) Раскрытый узел обозначать картинкой:

2) Выделенный конечный узел (лист) обозначать картинкой:

3) При выделении конечного узла (листа) отображать связанный с ним объект — «RichEdit» (компонент для вывода текста).

4) Управление деревом осуществлять программно.

Подготовительные шаги.
Программное создание компонентов «ListBox» и «Edit»

В создаваемом нами дереве имеется четыре конечных узла (листа). К каждому из них надо поставить в соответсвие свой объект «RichEdit» (как это сделать, смотри ниже).

Создание объектов будем производить в обработчике события формы «FormCreate».

Так как необходимо иметь доступ к компонентам «RichEdit» из любой процедуры или метода, то объявляем их через глобальные переменные «re1,re2,re3 и re4»:

var
Form1: Tform1;
re1,re2,re3,re4:TRichEdit ;
ed:TEdit;

implementation

{$R *.dfm}

Далее в методе формы «procedure TForm1.FormCreate(Sender: Tobject);» создаём соответсвующие объекты и задаём их свойства: координата левого края, координата верхнего края, ширина, высота, видимость, назначаем родителя и размещённый в компоненте текст.

re1:=TRichEdit .Create(self);//создаём объект re1
re2:=TRichEdit .Create(self);
re3:=TRichEdit .Create(self);
re4:=TRichEdit .Create(self);

with re1 do
begin
Left:=250; //координата «x» левого верхнего угла компонента
Top:=70; //координата «y» левого верхнего угла компонента
Width:=100; //ширина компонента
Height:=100; //высота компонента
Visible:=false; //видимость компонента (компонент невидим)
Parent:=self;//назначаем родительский компонент («self» – ссылка на «Form1». Обращение к ссылке «self» внутри методов класса «TForm» Родительский компонент необходимо назначать только для визуальных компонент. Родительский компонент будет отвечать за отображение на себе дочернего компонента и передавать ему сообщения от «Windows»
Text:=’узел 11’+#13#10+’текст 1′;//благодаря применению служебных символов «#13 — перевод на новую строку» и «#10 — вернуть курсор в начало строки» текст в компоненте будет отображён на двух строках.
end;

Оператор «with» используется в случае, когда повторяется какая-либо часть составного оператора. Например, re2. Left, re2.Top, re2. Width и так далее.

with re2 do
begin
Left:=250; Top:=70; Width:=100; Height:=100; Visible:=false; Parent:=self;
Text:=’узел 121’+#13#10+’текст 2′;
end;

with re3 do
begin
Left:=250; Top:=70; Width:=100; Height:=100; Visible:=false; Parent:=self;
Text:=’узел 13’+#13#10+’текст 3′;
end;

with re4 do
begin
Left:=250; Top:=70; Width:=100; Height:=100; Visible:=false; Parent:=self;
Text:=’узел 1’+#13#10+’текст 4′;
end;

Аналогично, для отбражения заголовков раздела создадим четыре компонента «TEdit».

ed:=TEdit.Create(self);
ed.Parent:=self;
with ed do
begin
top:=40; left:=225; width:=130; height:=22; visible:=false;
end;

Далее (для трениорвки) привязывем объект «ed» к свойству «Data» каждого «листа»:

TreeView1.Items[1].Data:=ed;
TreeView1.Items[3].Data:=ed;
TreeView1.Items[4].Data:=ed;
TreeView1.Items[5].Data:=ed;

Возврат иконок листов в исходное состояние

Обавим в классе «TForm1» метод «NodeBlue».

Type
TForm1 = class(TForm)

TreeView1: TtreeView;
ImageList1: TimageList;

procedure FormCreate(Sender: Tobject);
procedure TreeView1Change(Sender: TObject; Node: TtreeNode);
procedure NodeBlue;
procedure TreeView1Expanded(Sender: TObject; Node: TtreeNode);
procedure TreeView1Collapsed(Sender: TObject; Node: TtreeNode);
private
{ Private declarations }
public
{ Public declarations }
end;

Реализация метода «NodeBlue»:

procedure Tform1.NodeBlue;
var i:integer;
begin
//сбрасываем картинки всех «листов» в состояние «не выбран»
for i:=0 to TreeView1.Items.Count-1 do
begin
if not TreeView1.Items[i].HasChildren then//Если узел не имеет дочернего узла, то он является «листом»
begin
TreeView1.Items[i].ImageIndex:=4;//лист в состоянии «не выбран»
TreeView1.Items[i].SelectedIndex:=4;//лист в состоянии «выбран»
end;
end;

re1.Visible:=false;//делаем компонент «RichEdit» невидимым
re2.Visible:=false;
re3.Visible:=false;
re4.Visible:=false;

end;

Здесь «TreeView1.Items.Count» — общее количество узлов в дереве.

Свойство «TreeView1.Items[i].HasChildren» определяет, есть ли у узла дочерний узел (если нет, то этот узел является «листом»).

Для всех листов устанавливаем изображение:

вне зависимости от того, выбран «лист» или нет.

Подсветка выбранного «листа» и смена картинки узла.

Осталось реализовать решение задачи о смене изображения для «листа» в состоянии «выбран» и для узла в развёрнутом состоянии.

Выбранному листу будет соответствовать картинка:

Развёрнутому узлу сопоставлена картинка:

Основная часть программы.

Основная часть программы реализована в обработчике события «OnChange»

После щелчка по узлу он становится выбранным и поле текста узла окрашивается в синий цвет. При смене выделенного узла происходит событие «OnChange» и вызывается обработчик события — процедура «TreeView1Change(Sender: TObject; Node: TtreeNode);».

Аргумент «Node» — ссылка на выбранный узел.

procedure TForm1.TreeView1Change(Sender: TObject; Node: TtreeNode);
var b:boolean; i:integer;
begin

b:=node.HasChildren;//проверяем, имеет ли выбранный узел дочерний узел. Если не имеет, то «b=false»
if (not b) then//если выбранный узел не имеет дочернего узла (то есть является листом), то логическое выражение (not b) будет равно «true»
begin
NodeBlue;//сбрасываем иконки «листов» в состояние «не выбран»

//в зависимости от того, какой узел выбран, делаем видимым соответствующий компонент «RichEdit», и формируем текст компонента «Edit»
i:=node.AbsoluteIndex;
case i of
1: begin
re1.Visible:=true; //делаем видимым компонент «re1» (компонент типа «TRichEdit»)
ed:=node.Data; //возвращаем ссылку на компонент типа «TEdit», хранящуюся в свойстве узла «Data»
ed.Visible:=true;//делаем компонент «ed» видимым
ed.Text:=’заголовок для узла 11‘;
end;
3: begin re2.Visible:=true; ed:=node.Data; ed.Visible:=true;
ed.Text:=’заголовок для узла 121′; end;
4: begin re3.Visible:=true; ed:=node.Data; ed.Visible:=true;
ed.Text:=’заголовок для узла 13′; end;
5: begin re4.Visible:=true; ed:=node.Data; ed.Visible:=true;
ed.Text:=’заголовок для узла 1′; end;
end;

node.ImageIndex:=5;
node.SelectedIndex:=5;
end ;

end;

Теперь, после щелчка по «листу», дерево будет иметь следующий вид. Кроме того, отобразится заголовок, привязанный к данному листу и соответствующий компонент «RichEdit»:

Из рисунка видно, что рисунок около развёрнутого узла тоже изменил свой вид. Смена вида картинки в соответсвии с сотоянием узла развёрнут/свёрнут осуществляется в обработчиказ события «узел распахнут и «узел свёрнут».

//событие наступает после того, как узел оказывается в распахнутом состоянии
procedure TForm1.TreeView1Expanded(Sender: TObject; Node: TtreeNode);
begin
node.ImageIndex:=3;
node.SelectedIndex:=3;
end;

//событие наступает после того, как узел оказывается в свёрнутом состоянии
procedure TForm1.TreeView1Collapsed(Sender: TObject; Node: TtreeNode);
begin
node.ImageIndex:=2;
node.SelectedIndex:=2;
end;

Размещение сразу двух картинок около узла рассмотрено в «Delphi. Панель Win32. Компонент TreeView. Часть 5«

Предыдущая статья «Delphi. Панель Win32. Компонент TreeView. Часть 3.2«

Обновлено: 14.11.2021 — 13:16

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *