Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.04.24;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.008 c
7-77174
MetalFan
2003-03-05 15:05
2003.04.24
путь к


14-77142
Часто тут бываю
2003-04-08 14:14
2003.04.24
Рассылка


7-77198
KpeHgeJIb
2003-03-05 20:52
2003.04.24
Подскажите как получить иконку.......


14-77083
Феликс
2003-04-07 03:05
2003.04.24
В боях за Басру погибли трое военнослужащих Британии. (rbc.ru)


1-77000
acsoft
2003-04-09 07:55
2003.04.24
Помогите создать кнопку при помощи DLL.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский