Назад Оглавление Дальше Применение компонента TTreeView для работы с данными, имеющими структуру дерева


Содержание задания

  1. Разработать приложение, компонент класса TTreeView которого отображал бы структуру данных, изображенных на рисунке Вашего варианта.
  2. На форме должны быть кнопки для быстрого разворачивания и сворачивания схемы. В свернутом состоянии должны быть видны только узлы верхнего уровня. Возможно, это один узел ( директор предприятия). В развернутом состоянии должны быть видны все узлы. Каждому прямоугольнику с надписью соответствует узел дерева. В отличие от бинарных деревьев, в Делфи есть возможность формировать деревья, у которых каждый узел может иметь много подчиненных узлов.
  3. Смысл работы заключается в том, что структура дерева позволяет быстро добраться до любого узла ( если знаешь путь к нему, как в проводнике Windows ). Но, добравшись до узла нужно подумать -: а зачем я здесь? Дело в том, что каждый узел может хранить любую информацию и мы можем ее получить. Если узлом является планово-финансовый отдел, то информация может содержать описание: его роль в управлении предприятием. У него могут быть подчиненные узлы, например, сотрудники ПФО, тогда эти узлы могут содержать анкетные сведения о сотрудниках. Можно сделать для себя приложение, описывающее Вашу музыкальную коллекцию. Она будет иметь структуру дерева, так как существуют жанры, внутри жанров – направления. Узла жанров могут описывать особенности жанра, его историю. Узлы музыкальных произведений – ссылки на файлы с записями или фото исполнителей. Так что Ваше приложение должно иметь возможность записывать такую информацию в узлы и прочитывать. Фактически проще всего записывать информацию в файлы, причем в качестве имени файла брать текст, записанный в узле. Если информация текстовая, то к имени файла приписать расширение .txt. Если информация в виде графического файла, то мы находим ее где-то на диске и записываем в свою папку под именем текста выбранного узла, но с прежним расширением.
  4. В вариантах 1-11 приложение должно выводить информацию об узле в текстовом виде, в окно компонента Memo, а в вариантах 12 – 20 информация должна выводиться в виде картинки в окне компонента Image. И в том и в другом случае узел хранит в информационном поле только ссылку на имя файла, в котором хранятся данные.
  5. Как это делается - рассмотрено на примере

Описание (поэтапное) выполнения примера. (создавалось в Делфи3)

Исходные данные – структура управления фирмой

TTreeView

1-й этап – на форму поставлен компонент TTreeView и 2 кнопки.

TTreeView

Тексты обработчиков щелчков по кнопкам:

procedure TForm1.btnRazvernutClick(Sender: TObject);
begin {кнопка Развернуть}
 TreeView1.FullExpand;
end;

procedure TForm1.btnSvernutClick(Sender: TObject);

begin  {кнопка Свернуть} 
  TreeView1.FullCollapse;
end;

Чтобы создать и заполнить структуру данных – дерево:

Сделайте дв щелчок по компоненту TTreeView, расположенному на форме (находясь в среде Делфи ). Появится окно. Щелкайте кнопку NewItem, чтобы добавить узел этого же уровня или щелкайте NewSubItem, чтобы добавить узел подчиненного уровня. Заполните свойства узла (Item Properties). Для начала – только Text – это текст узла. Кстати, текст узла можно редактировать во время работы приложения. Когда Вы создадите список иконок, можно будет за каждым узлом закрепить иконки: одну - для обычного состояния ( ImageIndex ), другую – для выделенного (SelectedIndex). Щелкайте крестик узла, чтобы увидеть подчиненные узлы. Можно выделять узлы в любом порядке и добавлять в дерево узлы этого же уровня или подчиненные. Есть кнопка для удаления узлов.

Чтобы не потерять проект при аварийных ситуациях: Не забывайте иногда сохранять приложение в процессе разработки (кнопка Сохранить всё )


2-й этап – создадим список иконок (ImageList)

ImageList
  1. Будем использовать иконку для обозначения коллектива (отдел, цех – индекс=2 ) и другую (индекс = 0)– для обозначения сотрудника (Руководитель, Иванов). Третья иконка (индекс=1)– для обозначения выделенного состояния. Можете организовать это по - своему. .Найдите 3 подходящие иконки. Переименуйте в icon0.ico, icon1.ico, icon2.ico и поместите в папку с проектом.
  2. Поставьте на форму компонент ImageList1.
  3. Свойству Images компонента TTreeView1 присвойте (выберите в инспекторе объектов) ImageList1.
  4. Создайте шаблон обработчика события FormCreate и впишите в него примерно следующее:
procedure TForm1.FormCreate(Sender: TObject);
var ic1: TIcon; ii:Integer;
begin
 ImageList1.masked:= false; ImageList1.Height := 16; {свойства ImageList1 }
 ImageList1.Width := 16; ImageList1.AllocBy := 4;

 ic1:= TIcon.Create; {создаем объект ic1 для чтения иконок}
  for ii:=0 to 2 do
   begin  ic1.LoadFromFile('.\icon'+intToStr(ii)+'.ico');
     ImageList1.AddIcon(ic1); {здесь мы заполняем этот список ImageList1}
   end;
 ic1.free; 
end;

Примечание: как создать обработчик этого события ?

В режиме разработки приложения выделить форму, т е щелкнуть по ней. Далее в окне инспектора объектов убедиться, что выделена форма ( в верхнем окошке написано – Form1), перейти на закладку Events ( события) , найти строчку OnCreate и сделать двойной щелчок в правой части этой строчки (где мигает курсор и есть кнопочка с треугольником). В результате в редакторе будет создана заготовка (т е просто заголовок, begin и end ) обработчика события «создание формы». Операторы, которые Вы впишете между begin и end будут выполнены при создании формы. Перед begin можно (если нужно) вставить описания (констант, типов, переменных, меток, подпрограмм)

Запустите программу, она должна работать.


3-й этап – создадим файлы на диске, в которых хранится информация об узлах.

ImageList

Поставим на форму 3 кнопки: «Найти текстовый файл», «Найти картинку» и «Записать», а также компоненты OpenDialog1 – для поиска файла на диске для открытия файла и SaveDialog1 – для поиска места на диске, где записать файл и вписывания имени файла. Диалоговые компоненты нужно слегка настроить: InitialDir = . (точка) – что означает, что вначале будем искать файлы в папке, из которой запущена программа. Filter = ‘Текстовые файлы|*.txt’ – что означает, что видны будут только файлы с расширением txt. Filter = ‘ Графические|*.bmp;*.jpg’ - что означает, что видны будут только файлы с расширением bmp и jpg .

Кнопка «Найти текстовый файл»

помогает найти текстовый файл и записывает его содержимое в окно компонента Memo1. Затем мы можем отредактировать этот текст (т е из характеристики Иванова сделать характеристику Петрова) и записать (кнопка «Записать»)

Текст обработчика щелчка по этой кнопке:

procedure TForm1.Button3Click(Sender: TObject);
begin 
  OpenDialog1.Filter := 'Тексты |*.txt';
 If OpenDialog1.Execute then
    Memo1.Lines.LoadFromFile(OpenDialog1.FileName);
end;

Кнопка «Найти картинку»

помогает найти графический файл (*.bmp,*.ico,*.jpg) и показывает его содержимое на форме Form2

Текст обработчика щелчка по этой кнопке:

procedure TForm1.Button2Click(Sender: TObject);
var FN,Ext : String;
begin Form2.Image1.Picture.Graphic := Nil; {перестраховка}
 Form2.OpenPictureDialog1.Filter:= 'Все: |*.bmp;*.jpg’;
 If  Form2.OpenPictureDialog1.Execute then {диалог поиска файлов}
  begin  FN := Form2.OpenPictureDialog1.FileName; FileName - имя найденного файла.

   try
    Form2.Image1.Picture.LoadFromFile(FN);
      // читаю файл
   except
    Form2.Image1.Picture.Graphic := nil;
      //если ошибка 
   end;
   Ext := UpperCase(ExtractFileExt(FN));
     //Привожу к верхнему регистру. 
   ImageExt:= Ext;
     // запоминаю расширение. Переменная используется при записи картинки в файл. ( см
     // Form1.Button1Click )
   If Form2.Image1.Picture.Graphic.Empty then exit;
     // если картинки нет
   If Ext = '.JPG' then Form2.SetJPEGOptions(Sender);
     // если расширение = JPG (процедура SetJPEGOptions
      // настраивает отображение картинки и находится в модуле Unit2. см ниже )
   Ramka; Form2.Show;
     // - показать форму2 (с картинкой)  
  end;
end;

Примечания:

  1. в фильтр OpenPictureDialog1 добавляется *.jpg (если они есть. Можно исключить файлы JPG из Вашей работы.)
  2. procedure TForm2.SetJPEGOptions записывается в модуле Unit2 (см создание второй формы )
  3. Установите св-во Hint объекта TTreeView = ‘Щелчок – показ текста, дв щелчок – показ картинки’ и св-во ShowHint = true.
  4. Для показа картинки было решено использовать вторую форму. Об этом – см создание второй формы
  5. Процедура Ramka – служит для установки размеров формы в соответствии с размерами картинки. Вот ее текст:
    Procedure Ramka;
    begin
     Form2.Image1.Height := Form2.Image1.Picture.Height;
     Form2.Image1.Width := Form2.Image1.Picture.Width;
     Form2.ClientHeight := Form2.Image1.Height+3;
     Form2.ClientWidth := Form2.Image1.Width+3;
    end;

Одиночный щелчок по списку

Рассмотрим что происходит при одиночном щелчке по какой либо строке списка. Естественно, соответствующий узел становится выбранным (Selected). Как было сказано, должен прочитаться текстовый документ, имя файла которого равно тексту узла. Поэтому можно сочинить такой обработчик:

procedure TForm1.TreeView1Click(Sender: TObject);
begin
  If TreeView1.Selected = Nil then
  begin ShowMessage('Выбери строку'); exit
  end;
  FName := TreeView1.Selected.Text;

  edit1.Text := FName; {имя заносится в окошко Edit1 (излишество) }
  If FileExists(Dira+'\'+FName+'.txt') then
   begin Memo1.Clear;
     Memo1.Lines.LoadFromFile(Dira+'\'+FName+'.txt');
   end else  Memo1.Clear;- если файла нет, окошко Memo1 очищается 
end;

Двойной щелчок по списку

Рассмотрим что происходит при двойном щелчке по какой либо строке списка. Естественно, соответствующий узел становится выбранным (Selected). Как было сказано, должна прочитаться картинка, имя файла которой равно тексту узла. Поэтому можно сочинить такой обработчик:

procedure TForm1.TreeView1DblClick(Sender: TObject);
begin  Form2.Hide; прячется форма2 
  If TreeView1.Selected = Nil then
  begin ShowMessage('Выбери строку'); exit
  end;
  FName := TreeView1.Selected.Text; имя файла берется из свойства Text 
  edit1.Text := FName; 

  If FileExists(Dira+'\'+FName+'.bmp') or
     FileExists(Dira+'\'+FName+'.jpg') then если найден файл 
   begin Form2.Image1.Picture.Graphic := Nil;
     Form2.OpenPictureDialog1.InitialDir:='.\'; 
   end;

  If FileExists(Dira+'\'+FName+'.bmp') then
   begin
  Form2.OpenPictureDialog1.FileName:=Dira+'\'+FName+'.bmp'; установить имя файла 
 Form2.OpenPictureDialog1.Filter:='BMP|*.bmp'; установить фильтр 
 Form2.Image1.Picture.LoadFromFile(Dira+'\'+FName+'.bmp'); загрузить файл
     Ramka; - установить размеры формы-2 
     Form2.caption := 'Сотрудник: '+FName; заголовок формы 
     Form2.Show; - показать форму-2 
   end;
 If FileExists(Dira+'\'+FName+'.jpg') then

   begin Form2.OpenPictureDialog1.FileName:=Dira+'\'+FName+'.jpg';
     Form2.OpenPictureDialog1.Filter:='JPG|*.jpg';
     Form2.Image1.Picture.LoadFromFile(Dira+'\'+FName+'.jpg');
     Form2.SetJPEGOptions(Sender);
    Ramka;
    Form2.caption := 'Сотрудник: '+FName;
    Form2.Show;
    form2.top := 4; form2.Left := 4; форму поставить в лев –верх угол. 
   end;
end;
Примечания:
  1. непонятно, как работает OpenPictureDialog1 без Execute, но это подобрано опытным путем (открыть без выбора файла из списка )
  2. одновременно срабатывает и процедура одиночного щелчка, но вреда от этого вроде бы нет.

Кнопка «Записать» - Button1

Эта кнопка производит запись данных на диск. При этом проверяется: если число строк в Memo1 > 0 то содержимое Memo1 записывается в файл. Имя файла образуется из имени папки –Dira - из которой запущено приложение (чтобы записывать в свою папку) плюс текст выделенного узла + расширение txt. Аналогично, проверяется, есть ли картинка в форме2 (высота картинки, Form2.Image1.Picture.Height > 2 )

procedure TForm1.Button1Click(Sender: TObject);
Var textB, ImageB: Boolean; 
begin
 If TreeView1.Selected = Nil then
  begin ShowMessage('Выбери строку'); exit
  end;
 FName := TreeView1.Selected.Text;
 TextB := Memo1.Lines.Count > 0; - есть текст в Memo1 
 ImageB := Form2.Image1.Picture.Height > 2; - есть картинка в форме2 

 If textB and
  (MessageDlg('Записать из окна Memo в текстовый файл: '+
  FName+'.txt ?',mtConfirmation, [mbYes,mbNo],0) = mrYes ) then
   Memo1.Lines.SaveToFile(Dira+'\'+FName+'.txt');

 If ImageB and
  (MessageDlg('Записать картинку в файл: '+
   FName+' ?',mtConfirmation, [mbYes,mbNo],0) = mrYes ) then
   Form2.Image1.Picture.SaveToFile(Dira+'\'+FName+ImageExt);
end;
Примечания:

Рассмотрены все процедуры программы.


Создание второй формы

Создание второй формы – это дополнительные хлопоты, но зато можно красиво показать картинку – чтобы она занимала всю поверхность формы и размеры формы подстраивать под размер картинки.

  1. Работая с проектом в среде Делфи выберите меню: File\NewForm На экране появится форма2. Сделайте её небольшой, т к размеры будут устанавливаться автоматически. Поставьте на эту форму компонент для работы с изображениями: Image1. и установите компонент OpenPictureDialog1.
  2. Запишите процедуру настройки для файлов JPG : (ниже см полный текст модуля Unit2)
    unit Unit2; interface uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, ExtCtrls, ExtDlgs;
    
    type
      TForm2 = class(TForm)
        Image1: TImage;
        OpenPictureDialog1: TOpenPictureDialog;
      private
      public
      procedure SetJPEGOptions(Sender: TObject);
      end;
    
    var Form2: TForm2;
    
    implementation uses JPEG;
    
    {$R *.DFM}
    
    procedure TForm2.SetJPEGOptions(Sender: TObject);
    var
      Temp: Boolean;
    begin
      Temp := Image1.Picture.Graphic is TJPEGImage;
      if Temp then 
        with TJPEGImage(Image1.Picture.Graphic) do
        begin свойства изображения 
          PixelFormat :=jf24Bit;
          Scale := jsFullSize; полный размер (можно 1/2 ... 1/8 )
          Performance :=jpBestQuality;  {TJPegPerformance }
          ProgressiveDisplay := true;
        end;
      Image1.IncrementalDisplay := true;
    end;
    
    end.
  3. Добавленный модуль нужно сохранить: Меню\File\Save. Не забудьте указать папку для хранения. Это должна быть папка проекта. Добавьте этот модуль к проекту. – Меню\Project\Add To Project и в окошке выберите Unit2. Если, продолжая работу Вы не увидите формы2 или Unit2, то Меню\View\Forms и в этом окошке сделайте дв щелчок на Form2. Аналогично, если хотите увидеть Form1. Чтобы увидеть тексты модулей, то Меню\View\Units
  4. Так как из процедур модуля Unit1 происходят вызовы объектов модуля2, (например - Form2.Image1.Picture.Graphic := Nil; - «Найти картинку» - см выше ) то нужно включить Unit2 в предложение uses модуля Unit1:
     implementation  uses Unit2,JPEG;
     здесь модуль JPEG нужен для работы с файлами JPG 
    

Скачать RAR-архив исходников (компилируется в Д6,7) (27 Кб)
Скачать RAR-архив исходников + .exe(600 Кб)

Назад Дальше
Rambler's Top100
Hosted by uCoz