Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.03.04;
Скачать: [xml.tar.bz2];




Вниз

Общие соображения о межкомпонентной привязке изменений свойств 


AZ   (2002-02-15 07:40) [0]

Требуется в DesignTime произвести привязывание изменения состояния свойства (или нескольких свойств) в одном компоненте к анализаторам этого свойства в других с помощью редактора компонента. Анализ изменений будет производится в RunTime.
Все компоненты - потомки TGraphicControl.
1. Каким путем осуществить такую привязку?
Можно методом рассылки сообщений по списку (совет Набережных С.). Но метод, мне чем-то не нравится, не совсем элегантный, что ли.
2. Чем лучше редактировать такие связки? Редактор компонента (для каждого) или эксперт (для всех компонентов сразу)?
Какие еще решения можете посоветовать?
Может, для этого использовать интерфейсы ToolsAPI? Если да, то какие?
Я не прошу конкретных решений, просто выскажите общие соображения об этом.



AZ   (2002-02-15 07:47) [1]

В догонку.
Поместил просьбу в этот раздел, т.к. тематика, по моему, не совсем подходит к общему разделу.



Юрий Зотов (M)   (2002-02-15 10:08) [2]

IMHO, рассылка по списку - самое то. А Общий эксперт или отдельные редакторы - это уже как лучше и удобнее.

Что касается использования интерфейсов OTAPI, то для run-time их придется реализовывать ручками.



AZ   (2002-02-15 11:07) [3]

Это относительно оповещений.
А как редактировать список - извлекать при помощи ToolsAPI полный список компонентов и из него делать список рассылки?
Тогда какие интерфейсы использовать?



Юрий Зотов (M)   (2002-02-15 11:46) [4]

Если я правильно понял задачу, то сделал бы примерно так.

Пишем общий юнит, в котором создаем список рассылки:

interface

var
NotifyList: TList;

implementation

initialization

NotifyList := TList.Create;

finalization

NotifyList.Free

end.

В этом же юните пишем общий предок для всех Ваших TGraphicControl"ов.

constructor TMyGraphicControl.Create(...);
begin
inherited;
NotifyList.Add(Self)
end;

destructor TMyGraphicControl.Destroy;
begin
NotifyList.Remove(Self);
inherited
end;

procedure TMyGraphicControl.NotifyAll(сделанное_изменение);
var
i: integer;
begin
for i := 0 to NotifyList.Count - 1 do
if NotifyList[i] <> Self then
TMyGraphicControl(NotifyList[i]).ListNotification(Self, сделанное_изменение)
end;

procedure TMyGraphicControl.ListNotification(Sender: TMyGraphicControl; AChange: Tсделанное_изменение));
begin
// Здесь выполняем нужный анализ и делаем все остальное.
end;

Вот и все. Теперь, чтобы уведомить других о своем изменении, любой Ваш контрол просто вызывает метод NotifyAll из любого места своего кода и передает ему <сделанное_изменение>.

Если же общий предок Вас не устраивает, то всю ту же самую функциональность надо реализовать в отдельном объекте, экземпляр которого создается в каждом Вашем контроле и вся работа идет через него.



Юрий Зотов (M)   (2002-02-15 11:54) [5]

Забыл сказать - метод ListNotification в TMyGraphicControl можно сделать абстрактным. Как минимум, он должен быть виртуальным, чтобы любой класс-потомок мог производить свой индивидуальный анализ.



AZ   (2002-02-15 12:27) [6]

Спасибо за исчерпывающий ответ.
Наверное, я все же некорректно сформулировал задачу.
Я хочу создать пакет компонентов (практически работающие болванки их всех уже есть).
Теперь возникла необходимость организовать их взаимодействие встраиванием в них анализаторов состояния некоторых других компонентов (из этого же пакета). Эти связи (направления оповещения) должны редактироваться (переключиться с одного компонента на другой) в DesignTime.
Каким именно способом это лучше организовать?



Юрий Зотов (M)   (2002-02-15 12:46) [7]

Дык... елки-палки, Вы все же скажите ТОЧНО: design-time или run-time. А то сначала одно, потом другое...



paul_shmakov   (2002-02-15 13:04) [8]

если я правильно понял вопрос, то решение аналогично совету Юрия Зотова.
скажем, есть два компонента: TMyComponent и TMyListener. у TMyComponent есть свойство MyProperty, за изменениями которого должен следить компонент TMyListener. тогда


unit Unit1;

interface

uses Classes, Controls;

type

IEventListener = interface
procedure ProcessEvent(Sender: TObject);
end;

TMyComponent = class(TGraphicControl)
private
FMyProperty: Integer;
FListeners: TList;

procedure SetMyProperty(const Value: Integer);

public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;

procedure AddEventListener(Listerner: IEventListener);
procedure RemoveEventListener(Listerner: IEventListener);

published
property MyProperty: Integer read FMyProperty
write SetMyProperty;
end;

TMyListener = class(TGraphicControl, IEventListener)
private
FMyComponent: TMyComponent;
procedure SetMyComponent(const Value: TMyComponent);

protected
procedure ProcessEvent(Sender: TObject);

published
property MyComponent: TMyComponent read FMyComponent write SetMyComponent;
end;

implementation

uses Dialogs, SysUtils;

{ TMyComponent }

procedure TMyComponent.AddEventListener(Listerner: IEventListener);
begin
FListeners.Add(Pointer(Listerner));
end;

constructor TMyComponent.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FListeners := TList.Create;
end;

destructor TMyComponent.Destroy;
begin
FListeners.Free;
FListeners := nil;
inherited;
end;

procedure TMyComponent.RemoveEventListener(Listerner: IEventListener);
begin
FListeners.Remove(Pointer(Listerner));
end;

procedure TMyComponent.SetMyProperty(const Value: Integer);
var
I: Integer;
begin
FMyProperty := Value;

for I := 0 to FListeners.Count - 1 do
IEventListener(FListeners[I]).ProcessEvent(Self);
end;

{ TMyListener }

procedure TMyListener.ProcessEvent(Sender: TObject);
var
Comp: TMyComponent;
begin
Comp := TMyComponent(Sender);
ShowMessage(IntToStr(Comp.MyProperty));
end;

procedure TMyListener.SetMyComponent(const Value: TMyComponent);
begin
if Assigned(FMyComponent) then
FMyComponent.RemoveEventListener(Self);

FMyComponent := Value;

if Assigned(FMyComponent) then
FMyComponent.AddEventListener(Self);
end;

end.



т.е. описани интерфейс IEventListener, который должны реализовать все классы, которые заинтересованы в получении событий. далее эти классы вызывают метод AddEventListener у TMyComponent для добавления себя в список рассылки уведомлений.


> Эти связи (направления оповещения) должны редактироваться
> (переключиться с одного компонента на другой) в DesignTime.


ну а это получится автоматом - если установить вышеприведенный юнит, то в designtime при щелчке на свойство MyComponent компенента TMyListener появиться выпадающий список существующих компонентов TMyComponent.



AZ   (2002-02-15 13:09) [9]

Первоначальное сообщение:
>Требуется в DesignTime произвести привязывание изменения
^^^^^^^^^^
> состояния свойства (или нескольких свойств) в одном компоненте
>к анализаторам этого свойства в других с помощью редактора
>компонента. Анализ изменений будет производится в RunTime.
^^^^^^^
Уточнение:
>Теперь возникла необходимость организовать их взаимодействие
>встраиванием в них анализаторов состояния некоторых других
>компонентов (из этого же пакета). Эти связи (направления
>оповещения) должны редактироваться (переключиться с одного
>компонента на другой) в DesignTime.
^^^^^^^^^^
Извините за неоднозначность написания (и,естественно, прочтения).
Настройка взаимосвязей, естественно, в DesignTime. Работа по анализу состояния в DesignTime.



Юрий Зотов (M)   (2002-02-15 13:23) [10]

Или я совсем запутался, или это самые обычные события и их обработчики. Назначаем в design-time, работают в run-time.



AZ   (2002-02-15 15:45) [11]

>Юрий Зотов (M)
Вы правы. Но как это все организовать?



Юрий Зотов (M)   (2002-02-15 16:15) [12]

Дык... как обычно...

Посмотрите для примера, как реализовано в VCL событие OnChange. Вам надо сделать практически то же самое - разве что, еще нужно будет сделать в компонентах набор внутренних предопределенных обработчиков и редактор свойства, который только их и будет показывать в Инспекторе.



AZ   (2002-02-15 16:25) [13]

С обработчиками-то понятно.
Но выбор компонентов для присоединения?
Для этого нужно писать редактор компонента(для каждого) или эксперт (для всех компонентов сразу)?
Может, для этого использовать интерфейсы ToolsAPI? Если да, то какие? (Самоцитируюсь).



Юрий Зотов (M)   (2002-02-15 16:49) [14]

1. Определяете тип обработчика:
TMyChangeEvent = procedure(...) of object;

2. Во всех своих контролах делаете свойство:
OnMyChange: TMyChangeEvent

3. Пишете редактор этого свойства - TMyChangeProperty (потомок TMethodProperty). Он и будет делать все, что Вы хотите - в частности, формировать список обработчиков, выбирая их из нужных компонентов.

4. Регистрируете этот редактор для всех компонентов:
RegisterPropertyEditor(TypeInfo(TMyChangeEvent), nil, "OnMyChange", TMyChangeProperty);



MBo   (2002-02-15 16:56) [15]

а то, как, например, TUpDown.Associate работает, не похоже на твою задачу?



yaJohn   (2002-02-15 17:03) [16]

>Но выбор компонентов для присоединения?
Poprobuyte ob"yavit" otkompilirovat" i polojit" na formu.

published
property Target: TComponent raed FTarget write FTarget;

Vi eto imeli v vidu ;)

Potom prosto
if Target<>nil then Target.MyMetod.... Eto li ne posilka soobshenia? (V terminologii rannego ObjectPaskalia ;)

I ne zabivaem pro Notification....



AZ   (2002-02-15 17:10) [17]

>Юрий Зотов (M)
Приятно быть понятым, еще приятнее - получить дельный совет.
Большое спасибо!

>MBo ©
Спасибо. Обязательно посмотрю.



yaJohn   (2002-02-15 17:11) [18]

V dogonku. Iz Vashey postanovki ne yasno, vam nujen analog Observer iz Java? Componenti izmeniaushie svoe sostoianie opoveshaut component nabludatel". Odin? Mnogo?
Priviazka osushestvliaetsia u Nabludatelia ili u istochnika?
Mojno li ispolzovat" WinAPI?



AZ   (2002-02-15 17:27) [19]

К моему великому сожалению, Java не владею.
Оповещение может происходить как компонент-компонент, так и компонент-компоненты.
А относительно привязки, так это меня самого интересует, как это лучше организовать - редактором свойства у каждого компонента, или централизованно, экспертом.
К сожалению, Open Tools в литературе или нет, или освещены очень поверхностно.




Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.03.04;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.77 MB
Время: 0.039 c
1-9120            Марина                2002-02-04 16:25  2002.03.04  
MessageDlg


1-9241            yaJohn                2002-02-15 16:56  2002.03.04  
RUSSIAN_CHARSET


14-9274           jk                    2002-01-16 18:40  2002.03.04  
Гребаный ActiveX


1-9126            Olivka                2002-02-16 21:29  2002.03.04  
Окна: одно за другим ?


7-9320            AlexKniga             2001-11-27 18:10  2002.03.04  
Не в тему. Про аудио системы.