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

Вниз

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

Наверх





Память: 0.48 MB
Время: 0.038 c
4-1148964758
Шмель
2006-05-30 08:52
2006.10.15
Сохранение позиции окна


2-1159455089
RainKMM
2006-09-28 18:51
2006.10.15
Как заархивировать папку


15-1158834648
kroner
2006-09-21 14:30
2006.10.15
Работа с большими числами


2-1159637385
waaw
2006-09-30 21:29
2006.10.15
{$INCLUDE ...


3-1155684494
DimonS
2006-08-16 03:28
2006.10.15
Сбой в Access.





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский