Текущий архив: 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.5 MB
Время: 0.006 c