Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.04.24;
Скачать: CL | DM;

Вниз

Как правильно организовать подкомпоненты?   Найти похожие ветки 

 
Paladin ©   (2003-04-06 17:44) [0]

Привет Уважаемые Мастера!

Уже очень долго бъюсь над проблемой!
Сил больше никаких нет.
Нигде не смог найти доекментацию...

Пожалуйста Помогите!

Я делаю компонент TElemList, который содержит список других компонентов TElem.
Каждый TElem, кроме того, что содержится в TElemList, должен отражаться в виде свойства на форме.
Т.е. компоненты в этом плане должны быть похожи на TActionList и TAction

Но никак не могу добиться, чтобы dfm был в соответствующем виде.
Например у TActionList и TAction это выгляди так:

object ActionList1: TActionList
Left = 150
Top = 130
object Action1: TAction
Caption = "Action1"
end
object Action2: TAction
Caption = "Action2"
end
end


Action1 и Action2 находятся как бы внутри ActionList1.
Т.е.
У меня же получается только так:

object ElemList1: TElemList
Count = 0
Left = 42
Top = 168
end
object Elem1: TElem
Parent = ElemList1
end
object Elem2: TElem
Parent = ElemList1
end


И Elem-ты и Action-ны имеют одинаковый Owner - форму Form1, благодаря чему они появляются в виде свойств формы.
В Object Tree View TElem и TElemList выглядят так же, как и TAction и TActionList т.е. TElem находятся внутри TElemList благодаря тому, что у TElem перекрыт метод GetParentComponent.

Как добиться того, чтобы в .dfm - Elem1 и Elem2 находились внутри ElemList1, так же как и Action1 и Action2 находятся внутри ActionList1?


 
Юрий Зотов ©   (2003-04-06 19:44) [1]

Уточните - от чего наследуются TElem и TElemList?
От этого зависит решение.


 
paIadin   (2003-04-07 11:03) [2]

To Юрий
TElem = class(TComponent)
TElemList = class(TComponent)


 
Skier ©   (2003-04-07 11:30) [3]


> у TElem перекрыт метод GetParentComponent

Хорошо бы код увидеть...


 
Юрий Зотов ©   (2003-04-07 12:55) [4]

1. TElem:
- Никаких Parent вводить не нужно.
- RegisterNoIcon вместо RegisterComponents.
- Заместить GetParentComponent.

Посмотрите, как это сделано в TAction, TField, TMenuItem...


2. TElemList:
- При создании TElem вызывать его SetParentComponent (а никакое не Parent), Owner"ом ставить форму.
- Заместить Notification (удаление элемента из внутреннего списка при его уничтожении).

Посмотрите, как это сделано в TActionList, TDataSet, TMenu...


 
malkolinge(fp)   (2003-04-07 20:31) [5]

А я бы коллекцию сделал бы.....


 
Юрий Зотов ©   (2003-04-07 20:58) [6]

> malkolinge(fp) (07.04.03 20:31)
> А я бы коллекцию сделал бы.....

1. Не всегда подходит. Иногда функциональность требует, чтобы это были именно "лежащие на форме" невидимые компоненты (напр. связки TActionList-TAction, TDataSet-TField, TMenu-TMenuItem и т.п.).

2. Коллекции могут вызвать проблемы при визуальном наследовании форм. Там не просто Filer.Ancestor <> nil, там при изменении лишь одного Item"а пишется вся коллекция.


 
Юрий Зотов ©   (2003-04-07 23:40) [7]

> paIadin

Забыл добавить. У TElemList еще надо перекрыть GetChildren и, возможно, SetChildOrder (если "порядок имеет значение", как говорят преферансисты).


 
Paladin ©   (2003-04-07 23:55) [8]

Привет!

Спасибо за советы.
Особенно to Юрий Зотов!
Ход мыслей совершенно правильный.

Я наконец-то справился с проблемой!

Код приводить не стал, т.к. довольно громоздкий.
Но, как это решать - разобрался, и т.к. есть тонкости, и по этой задаче практически не нашел ни одной доки (кроме исходников TCustomActionList и TContainedAction), то в кратце поделюсь со всеми:

Итак:

От кого создавать:
TElem = class( TComponent)
TElemList = class( TComponent)

Важно знать:
- Owner - тот кто делает элементу Free. Т.е. кому принадлежит. Для TElem и TElemList Owner - форма, иначе они не будут появляться на форме в виде свойств.
- понятие Parent:
1) тот, кто пишет инфу в dfm
2) под кем будет рисоваться в Object Tree View
3) свойства Parent - нету, но есть такое понятие.

Как правильно определить Parent:
(нам нужно, чтобы у Elem парент был - ElemList)
- Для Elem:
1) Заводим приватное св-во для хранения Parent
2) При установке св-ва для хранения Parent не забываем в самом Parent запоминать что у него появился Child, например во внутреннем списке
3) Переопределяеми метод HasParent: Boolean -> true, после чего форма перестает прописывать Elem в dfm автоматически
4) Переопределяем метод GetParentComponent -> TElemList после чего в Object Tree View Elem начинает отображаться под TElemList
5) Не забываем переопределить, и при создании компонента вызывать - метод SetParentComponent для установки св-ва для хранения Parent.

- Все теперь Elem ведет себя как надо, только не сохраняется в dfm .

А вот, сохранять его в dfm должен его Parent.
Вопроc: Где он это должен делать?
Ответ: перекрыть метод GetChildren(Proc:TGetChildProc;... и после вызова inherited, еще для каждого Child-а вызвать Proc( Child), после чего Child-ы начнут появляться в dfm под Parent-ом т.е. так как и надо было:

object ElemList1: TElemList
...
object Elem1: TElem
...
end
object Elem2: TElem
...
end
end

- Теперь осталось только при загрузке самой формы, т.е. при считывании информации из dfm проследить, чтобы после загрузки список Child-ов был загружен. Сам он не загрузится.
Сдеать это надо у TElem, перекрыть метод ReadState.
у меня код получился такой:

procedure TElem.ReadState(Reader: TReader);
begin
inherited ReadState( Reader);
if Reader.Parent is TElemList then
Parent := TElemList( Reader.Parent); { здесь срабатывает write метод для свойства Parent - SetParent, котрый и добавляет текущий элемент в список Child-ов в TElemList. }
end;

Вот и все. Надеюсь - ничего не забыл.

Все это только общая схема, придется еще помучиться с мелочами. За памятью последить и т.д. У меня при самом написании - Delphi вылетел множество раз. Шаг влево - шаг вправо - вылетает...

Paladin ©


 
Юрий Зотов ©   (2003-04-08 00:32) [9]

> Ход мыслей совершенно правильный.

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

А дока... в хелпе все сказано, только скуповато написано.


 
ayder   (2003-04-09 17:04) [10]

А как сделать свойство аналогичное Fields в TTable (NoCathegory в ActionManager)? В исходниках TFields = class(TObject), у которого нет выше указаных методов (GetParentComponent, HasParent и т.д.).
Или, другими словами, как сделать так, чтобы у разных компонентов было свойство с одним и тем же именем и он отображался в Object TreeView как подкомпонент, а уже остальные элементы подкомпонентами данного.
Т.е. аналогично:
TTable
|_Fields
|_Field1
|_Field2


 
Paladin ©   (2003-04-10 09:22) [11]

to ayder
- Поясни, не понял, что ты хочешь?


 
Paladin ©   (2003-04-10 10:16) [12]

ayder натолкнул на мысль...
Я похоже понял, что он хотел спросить.
Теперь самому стало интересно.

Дествительно, что-то здесь не учтено!
А я то думал, что разобрался...

Видимо я ошибочно написал, что:
1) понятие Parent: под кем будет рисоваться в Object Tree View
2) Переопределяем метод GetParentComponent -> TElemList после чего в Object Tree View Elem начинает отображаться под TElemList

В описаном выше случае - это справедливо, Но!
Если случай немного сложнее, например, если список разбит на группы или категории?

У TAction, например есть понятие - категория.
Cписок TAction-ов, в Object Tree View отображается не под самим TActionList, который является для него Parent, т.е. у него GetParentComponent -> TActionList, а отображается под своей КАТЕГОРИЕЙ!
А категория - даже не наследник от TComponent, это обычный string!

Заметил, что в Object Tree View подобные элементы выглядят черно белыми, и при их выборе - в Object Inspector ничего не отображается.

Я попробовл реализовать так же, как это сделано у TAction, т.е. разбить TElem-сы на категории.

- ничего не получилось.

Вот тут без Мастеров не обойтись!
Помогите!

Как сделать так, чтобы в Object Tree View появился узел, который:
1) не является наследником от TComponent
2) является "группой" других подкомпонентов
3) под ним отображаются подкомпоненты, с другим Parent и Owner т.е. не равные ему самому.
4) например, аналогичный категории у TAction
5) например, аналогичный Fields у TDataSet (ayder)
???


 
ayder   (2003-04-10 11:07) [13]

> to paladin
Совершенно правильно понял.


 
Paladin ©   (2003-04-10 14:43) [14]

Да, очень интересно.
Все равно придется с этим мучиться!

Может кто знает как это сделать?


 
Paladin ©   (2003-04-12 12:06) [15]

Не ужели никто не знает :-(


 
veb   (2003-04-12 18:01) [16]

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



Страницы: 1 вся ветка

Текущий архив: 2003.04.24;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.016 c
14-77080
Lexa
2003-04-06 23:13
2003.04.24
Удаление CLX-компонентов


3-76860
Leviathan
2003-04-07 21:07
2003.04.24
Добавление записи через TQuery


3-76752
Юный_программер
2003-04-04 10:53
2003.04.24
что значит ошибка: BOF или EOF имеет значение True, либо текущая


3-76831
bars_gera
2003-04-07 18:45
2003.04.24
BLOB в DB Interbase


3-76759
Johnmen
2003-04-08 11:16
2003.04.24
Запросы