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

Вниз

Assign для наследника TCollectionItem   Найти похожие ветки 

 
Priest ©   (2006-02-26 16:51) [0]

Создаю свою коллекцию и класс производный от TCollectionItem. Элемент коллекции содержит ссылку на TButton. Коллекцию помещаю в виде publisher свойства в компонент. Компонент кладу в базовую форму и в коллекции создаю в Дезайн-Тайм несколько элементов. Потом создаю производную форму. В производной форме появляются все мои элементы. Но ссылки на кнопки появляются в виде Имяпеременной.Имя кнопки. В момент запуска происходит ошибка. Если я ручками строки Имяпеременной.Имя кнопки меняю на Имя кнопки, то всё работает. Как правильно писать метод Assign?


 
jack128 ©   (2006-02-26 17:48) [1]

посмотри вот здесь http://delphimaster.net/view/5-1133168076/
кажись твоя проблема...


 
Priest ©   (2006-02-27 10:13) [2]

Нет. Там что то не то


 
Юрий Зотов ©   (2006-02-27 12:26) [3]


unit RefToButton;

interface

uses
 Classes, StdCtrls;

type
 TYzItem = class(TCollectionItem)
 private
   FButton: TButton;
   procedure SetButton(const Value: TButton);
 protected
   procedure Notification(AComponent: TComponent; Operation: TOperation); dynamic;
   procedure AssignTo(Dest: TPersistent); override;
 published
   property Button: TButton read FButton write SetButton;
 end;

 TYzItems = class(TOwnedCollection)
 protected
   procedure Notification(AComponent: TComponent; Operation: TOperation); dynamic;
 end;

 TYzItemsContainer = class(TComponent)
 private
   FItems: TYzItems;
   procedure SetItems(const Value: TYzItems);
 protected
   procedure Notification(AComponent: TComponent; Operation: TOperation); override;
 public
   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override;
 published
   property Items: TYzItems read FItems write SetItems;
 end;

implementation

{ TYzItem }

procedure TYzItem.AssignTo(Dest: TPersistent);
begin
 if Dest is TYzItem then
   TYzItem(Dest).SetButton(FButton)
 else
   inherited
end;

procedure TYzItem.Notification(AComponent: TComponent; Operation: TOperation);
begin
 if (Operation = opRemove) and (AComponent = FButton) then
   FButton := nil
end;

procedure TYzItem.SetButton(const Value: TButton);
begin
 if FButton <> Value then
 begin
   if FButton <> nil then
     TComponent(Collection.Owner).RemoveFreeNotification(FButton);
   FButton := Value;
   if FButton <> nil then
     TComponent(Collection.Owner).FreeNotification(FButton);
   Changed(False)
 end
end;

{ TYzItems }

procedure TYzItems.Notification(AComponent: TComponent; Operation: TOperation);
var
 i: integer;
begin
 BeginUpdate;
 try
   for i := 0 to Count - 1 do
     TYzItem(Items[i]).Notification(AComponent, Operation)
 finally
   EndUpdate
 end
end;

{ TYzItemsContainer }

constructor TYzItemsContainer.Create(AOwner: TComponent);
begin
 inherited;
 FItems := TYzItems.Create(Self, TYzItem)
end;

destructor TYzItemsContainer.Destroy;
begin
 FItems.Free;
 inherited
end;

procedure TYzItemsContainer.Notification(AComponent: TComponent; Operation: TOperation);
begin
 inherited;
 if FItems <> nil then
   FItems.Notification(AComponent, Operation)
end;

procedure TYzItemsContainer.SetItems(const Value: TYzItems);
begin
 FItems.Assign(Value)
end;

end.


 
Priest ©   (2006-02-27 16:19) [4]

У меня точно так же реализовано. И Ващ код, так же как и мой не работает.
Я делал так. Взял Ваш код, добавил его в пакет и установил компонент в палитру. Потом в тот же пакет добавил форму и разместил на ней 2 кнопки. Создал два элемента, вот ДФМ

object Button1: TButton
   Caption = "Button1"
 end
 object Button2: TButton
   Caption = "Button2"
 end
 object YzItemsContainer1: TYzItemsContainer
   Items = <
     item
       Button = Button1
     end
     item
       Button = Button2
     end>
 end

Это у меня базовая форма. Я перебилдил пакет. И добавил в него производную форму. Вот что получилось в производной ДФМ.

inherited Form3: TForm3
 Caption = "Form3"
 OldCreateOrder = True
 PixelsPerInch = 96
 TextHeight = 13
 inherited YzItemsContainer1: TYzItemsContainer
   Items = <
     item
       Button = Form2.Button1
     end
     item
       Button = Form2.Button2
     end>
 end
end

То есть ссылка у меня не Button = Button1, а Button = Form2.Button1. Если я убираю слово Form2, то всё работает. Но если затем добавить в класс TYzItemsContainer какой либо метод или переменную, то опять прописывается Form2.
Как быть?


 
Юрий Зотов ©   (2006-02-27 20:03) [5]

Вряд ли стоит хранить формы в пакете - для этого есть репозиторий. И с ним все прекрасно работает (вот чес-слово, я не выкладываю непроверенный код).


 
Priest ©   (2006-02-28 09:09) [6]

Да проблема в том, что я потом форму использую в Dream Designer. Поэтому загоняю их в пакет.

>>вот чес-слово, я не выкладываю непроверенный код

Я не сомневаюсь. Но проделайте описанную мной последовательность и увидите тот же результат. Причём даже если удалиль глобальную переменную Form2, Дельфи всё равно сериализует вот так: Form2.Button2.

Я пробовал редактор свойста сделать и вырезать имя формы. В инспекторе отображается нормально, но в дфм пишется всё также.
Вобщем из решения я придумал лишь следующее. Делаю publisher свойство типа string, в котором заношу имя компонента-кнопки. В момент присвоения ищу данную кнопку на текущей форме и присваиваю своему, уже public свойству Button:TButton


 
Юрий Зотов ©   (2006-02-28 09:48) [7]

> Priest ©   (28.02.06 09:09) [6]

Не только в момент присвоения, еще и в Loaded. Причем в момент присвоения так:
if not (csLoading in ComponentState) then ...

Поскольку кнопка может грузиться и после компонента - то есть, в момент присвоения ее может еще не быть.


 
Priest ©   (2006-02-28 11:54) [8]

Не понял. Ведь я сохраняю только ссылку на кнопку. Ну и что если она ещё не загружена. Она ведь уже создана как объект. Просто не проиниированы свойства.


 
Юрий Зотов ©   (2006-02-28 12:31) [9]

> Priest ©   (28.02.06 11:54) [8]

При загрузке формы кнопка не создана, до тех пор, пока при чтении DFM до нее не дойдет очередь. Соответственно, если Ваш компонент визуальный и загружается раньше кнопки, то в методе SetButton получить ссылку на нее он не сможет (поскольку объекта-кнопки еще нет), а в Loaded - сможет.

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


 
Priest ©   (2006-02-28 12:57) [10]

Спасибо за терпение. учту



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

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

Наверх




Память: 0.5 MB
Время: 0.029 c
2-1159302430
aleko
2006-09-27 00:27
2006.10.15
прокрутка DBGrid колесом мыши


15-1158737267
Ega23
2006-09-20 11:27
2006.10.15
С Днём рождения! 20 сентября


2-1159263703
e_u_
2006-09-26 13:41
2006.10.15
структура


2-1159635006
Firedg
2006-09-30 20:50
2006.10.15
Работа с HTML


15-1158672385
ProgRAMmer Dimonych
2006-09-19 17:26
2006.10.15
Собрать много DJVU в 1