![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Assign для наследника TCollectionItem
Priest © (2006-02-26 16:51:00)Создаю свою коллекцию и класс производный от TCollectionItem. Элемент коллекции содержит ссылку на TButton. Коллекцию помещаю в виде publisher свойства в компонент. Компонент кладу в базовую форму и в коллекции создаю в Дезайн-Тайм несколько элементов. Потом создаю производную форму. В производной форме появляются все мои элементы. Но ссылки на кнопки появляются в виде Имяпеременной.Имя кнопки. В момент запуска происходит ошибка. Если я ручками строки Имяпеременной.Имя кнопки меняю на Имя кнопки, то всё работает. Как правильно писать метод Assign?
Priest (2006-02-28 12:57:00) [1]Спасибо за терпение. учту
Юрий Зотов (2006-02-28 12:31:00) [2]> Priest © (28.02.06 11:54) [8]
При загрузке формы кнопка не создана, до тех пор, пока при чтении DFM до нее не дойдет очередь. Соответственно, если Ваш компонент визуальный и загружается раньше кнопки, то в методе SetButton получить ссылку на нее он не сможет (поскольку объекта-кнопки еще нет), а в Loaded - сможет.
Если компонент невизуальный, он всегда будет загружаться позже кнопки.
Priest (2006-02-28 11:54:00) [3]Не понял. Ведь я сохраняю только ссылку на кнопку. Ну и что если она ещё не загружена. Она ведь уже создана как объект. Просто не проиниированы свойства.
Юрий Зотов (2006-02-28 09:48:00) [4]> Priest © (28.02.06 09:09) [6]
Не только в момент присвоения, еще и в Loaded. Причем в момент присвоения так:
if not (csLoading in ComponentState) then ...
Поскольку кнопка может грузиться и после компонента - то есть, в момент присвоения ее может еще не быть.
Priest (2006-02-28 09:09:00) [5]Да проблема в том, что я потом форму использую в Dream Designer. Поэтому загоняю их в пакет.
>>вот чес-слово, я не выкладываю непроверенный код
Я не сомневаюсь. Но проделайте описанную мной последовательность и увидите тот же результат. Причём даже если удалиль глобальную переменную Form2, Дельфи всё равно сериализует вот так: Form2.Button2.
Я пробовал редактор свойста сделать и вырезать имя формы. В инспекторе отображается нормально, но в дфм пишется всё также.
Вобщем из решения я придумал лишь следующее. Делаю publisher свойство типа string, в котором заношу имя компонента-кнопки. В момент присвоения ищу данную кнопку на текущей форме и присваиваю своему, уже public свойству Button:TButton
Юрий Зотов (2006-02-27 20:03:00) [6]Вряд ли стоит хранить формы в пакете - для этого есть репозиторий. И с ним все прекрасно работает (вот чес-слово, я не выкладываю непроверенный код).
Priest (2006-02-27 16:19:00) [7]У меня точно так же реализовано. И Ващ код, так же как и мой не работает.
Я делал так. Взял Ваш код, добавил его в пакет и установил компонент в палитру. Потом в тот же пакет добавил форму и разместил на ней 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 12:26:00) [8]
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 10:13:00) [9]Нет. Там что то не то
jack128 (2006-02-26 17:48:00) [10]посмотри вот здесь http://www.delphimaster.ru/cgi-bin/forum.pl?id=1133168076&n=12
кажись твоя проблема...