Здравствуйте! Есть тема "Иерархия структуры таблицы Менделеева", в пределах которой нужно построить иерархию объектов, состоящей как минимум из 3-х уровней. Для демонстрации работы построенной иерархии классов, создаётся приложение, позволяющее: создавать, удалять объекты, изменять характеристики объектов, визуализировать объекты, манипулировать на форме объектами, сохранять/считывать текущее состояние объектов в формате XML.
Есть некоторые задумки насчёт иерархии (изображение)...Может кто-нибудь подскажет другой подход? Ну а прежде всего - трудности с визуализацией и манипулированием объектами...Может быть у кого-нибудь есть идеи, как для начала идейно подойти к этим вопросам? что можно придумать? Подскажите пожалуйста..!
прежде всего - трудности с визуализацией и манипулированием объектами
Какие именно трудности возникли? Какими компонентами ты пользуешься для визуализации? То, что ты привела - это же TTreeView в чистом виде. Пробовала его?
Вот так выглядит:
В Дельфи7 точно уже был этот компонент.
Для манипулирования узлами дерева - Drag and Drop, в Drkb есть примеры реализации
interface type TBPeriod=class private fBTitle:string; function GetBTitle:string; procedure SetBTitle(newBTitle:string);
public property BTitle:string read GetBTitle write SetBTitle; constructor Create(fBTitle:string); end;
implementation Uses UnitMain;
constructor TBPeriod.Create(fBTitle:string); begin inherited Create; BTitle:=fBTitle; end;
function TBPeriod.GetBTitle:string; begin Result:=fBTitle; end;
procedure TBPeriod.SetBTitle(newBTitle:string); begin fBTitle:=newBTitle; end;
end.
На форме имеется кнопка, по которой предполагается создать объект класса TBPeriod (при установке переключателя в положение "Большой"), название его считывается из Edit, и я хочу добавить создаваемый объект в TreeViewNew, с чем и возникла проблема..
procedure TFormMain.BitBtnCreateBPerClick(Sender: TObject); var NewBPeriod:TBPeriod; title:string; begin case RadioGroupPeriod.ItemIndex of 0: begin title:=EditTitlePer.Text; NewBPeriod:=TBPeriod.Create(title); //Вот здесь меня не пропускает с несоответствием типов... Подскажите пожалуйста, как тут быть? FormMain.TreeViewNew.Items.AddObject(title, NewBPeriod as TObject); end; 1: ; else MessageDlg('Выберите пункт создания',mtError,[mbOK],0); end; end;
//Вот здесь меня не пропускает с несоответствием типов...
Правильно... AddObject принимает три параметра. Первый - Sibling, куда вставлять новый узел, ты про него забыла... Чтобы добавить еще один корневой узел - сделай:
FormMain.TreeViewNew.Items.AddObject(nil, title, NewBPeriod as TObject);
, ну или передавай вместо nil тот элемент, после которого будет вставлен новый. Проще всего выбрать нужный тебе узел, и сделать:
FormMain.TreeViewNew.Items.AddObject(FormMain.TreeViewNew.Selected, title, NewBPeriod as TObject);
, тогда новый узел добавится как сосед выбранного.
Вопрос насчёт создания класса-потомка для моего класса TBPeriod..
type TRange=class(TBPeriod) // .... end;
Если предполагается, что у этого класса-потомка будет поле, конструктор, так же как и у родителя, то нужно ли эти поле и конструктор писать снова для класса-потомка или можно использовать то, что есть у родителя? Объясните пожалуйста, как это будет выглядеть при описании классов?
Если предполагается, что у этого класса-потомка будет поле, конструктор, так же как и у родителя, то нужно ли эти поле и конструктор писать снова для класса-потомка или можно использовать то, что есть у родителя?
Для инициализации тех полей, которые есть у предка, используй конструктор предка (дя этого тот конструктор, собственно, и существует - чтобы правильно выделить и заполнить поля объекта, которые ему известны). Свой конструктор используется для инициализации новых полей:
type TPeriod = class title: string;
constructor create(const s: string); end;
TRange = class(TBase) min, max: integer; // только для иллюстрации, я не знаю, что ты хочешь хранить в этом классе constructor create(const s: string; amin, amax: integer); end;
constructor TPeriod.create(const s: string); begin inherited create; title := s; end;
constructor TRange.create(const s: string; amin, amax: integer); begin inherited create(s); // <--- Поля предка инициализированы ЕГО конструктором min := amin, max := amax; // А теперь инициализируем новые поля end;
Ещё один вопрос по классам... Есть класс TPeriod и его наследник TRange..
unit UnitClasses;
interface type TPeriod=class Title:string; Feature:string; constructor Create(s:string;aFeature:string); end;
type TRange=class(TPeriod) constructor Create(s:string); end;
Тогда при записи
implementation Uses UnitMain;
constructor TPeriod.Create(s:string;aFeature:string); begin inherited Create; Title:=s; Feature:=aFeature; end;
constructor TRange.Create(s:string); begin inherited Create(s); end;
end.
во 2-м конструкторе компилятор сигнализирует об ошибке..Природа этой ошибки мне ясна (не все параметры указаны)...Но как обойти эту ошибку? Ведь у меня в потомке только поле title без Feature...
Но как обойти эту ошибку? Ведь у меня в потомке только поле title без Feature...
Неправда... У тебя в потомке И title, И feature, поскольку оба этих поля описаны в предке... Понимаешь в чем дело? Если тебе хочется сделать так, чтобы потомок содержал меньше полей, чем предок - то налицо ошибка проектирования. У каждого потомка количество полей должно быть как минимум не меньше, чем у предка.
Неправда... У тебя в потомке И title, И feature, поскольку оба этих поля описаны в предке... Понимаешь в чем дело? Если тебе хочется сделать так, чтобы потомок содержал меньше полей, чем предок - то налицо ошибка проектирования. У каждого потомка количество полей должно быть как минимум не меньше, чем у предка.
Например, я добавила в TreeView объект с некоторыми характеристиками (в TreeView отображается из них заголовок)..Выделила его..Скажите пожалуйста, что нужно сделать, чтобы теперь просмотреть этот объект?
Совсем забыл уточнить, что для работы с TTreeView твои классы должны быть унаследованы от TObject... То есть, вот так:
type TBPeriod = class(TObject) // внимательно, наследник TObject !!! private fBTitle:string; function GetBTitle:string; procedure SetBTitle(newBTitle:string);
public sData: string; // Просто для иллюстрации - эта строка будет хранимой информацией property BTitle:string read GetBTitle write SetBTitle; constructor Create(fBTitle, data:string); end;
function TBPeriod.GetBTitle:string; begin Result := fBTitle; end;
procedure TBPeriod.SetBTitle(newBTitle:string); begin fBTitle := newBTitle; end;
procedure TForm1.BitBtn1Click(Sender: TObject); var NewBPeriod: TBPeriod; title: string; begin case RadioGroupPeriod.ItemIndex of 0: begin title := EditTitlePer.Text; NewBPeriod := TBPeriod.Create(title, Edit1.Text); TreeView1.Items.AddChildObject( // так заносим данные, это ты уже видела TreeView1.Selected, title, NewBPeriod as TObject ); end;
1: ;
else MessageDlg('Выберите пункт создания',mtError,[mbOK],0); end; end;
procedure TForm1.Button1Click(Sender: TObject); begin // А вот так - получаем доступ к данным ShowMessage(TBPeriod(TreeView1.Selected.Data).sData); end;
У меня возник вопрос по Drag&Drop.. Я хочу реализовать такое действие: при перетаскивании элемента из TreeView на Image соответствующий узел (и связанный с ним объект) удаляется.. Попыталась таким образом:
procedure TFormMain.ImageDelDragDrop(Sender, Source: TObject; X, Y: Integer); begin if Source = TreeViewNew then // Удаляем из источника TTreeView(Source).Items.Delete(TTreeView(Source).Selected); end;
procedure TFormMain.ImageDelDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin Accept := (Source = TreeViewNew); end;
Желаемые результаты не достигаются.. Объясните пожалуйста, как нужно сделать?
У меня возник вопрос по Drag&Drop.. Я хочу реализовать такое действие: при перетаскивании элемента из TreeView на Image соответствующий узел (и связанный с ним объект) удаляется.. Попыталась таким образом:
procedure TFormMain.ImageDelDragDrop(Sender, Source: TObject; X, Y: Integer); begin if Source = TreeViewNew then // Удаляем из источника TTreeView(Source).Items.Delete(TTreeView(Source).Selected); end;
procedure TFormMain.ImageDelDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin Accept := (Source = TreeViewNew); end;
Желаемые результаты не достигаются.. Объясните пожалуйста, как нужно сделать?
Этот пост - мое авторство..Случайно получилось под "Гость"
public sData: string; // Просто для иллюстрации - эта строка будет хранимой информацией function GetsData:string; procedure SetsData(newsData:string); property Data:string read GetsData write SetsData; constructor Create(fBTitle, data:string); end;
/////////// function TBPeriod.GetsData:string; begin Result:=sData; end;
procedure TBPeriod.SetsData(newsData:string); begin sData:=newsData; end;
В TreeView соответсвенно находится запись и связанный с ней объект..Выделяя эту запись, можем просмотреть значение поля sData. И предположим, пользователь захочет изменить это значение..А как это осуществить с помощью функции, процедуры и свойства моего класса? Не очень понятен механизм..объясните пожалуйста!