Пиктограммы около узлов дерева.
Как правило, около узлов дерева бывают размещены одна или две картинки — пиктограммы. Например:
Эти пиктограммы могут принимать два состояния: в зависимости от того, выделен узел или нет.
Рассмотрим последовательность шагов назначения пиктограммы узлу.
Во-первых, сами пиктограммы должны быть созданы. Это могут быть небольшие изображения типа «.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«