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

Вниз

TCollection. run-time VS desine-time   Найти похожие ветки 

 
DevilDevil ©   (2006-09-26 14:32) [0]

Программирую таблицу. Есть свойство ColsCount - количество столбцов. Каждому столбцу в таблице соответствует класс TCol.

Теобходимо написать редактор столбцов.

Для реализации этого свойства [Columns ...] использую коллекцию. Мне не хочется наследовать уже готовый TCol от TCollectionItem. Поэтому я реализую "соответствие"; в моём классе-элементе коллекции в разделе public содержится свойство Column : TCol.

При изменении количества столбцов (свойства ColsCount) соответствующим образом должна изменяться коллекция:

void __fastcall TInfoTable::SetColsCount(int Count)
{
...>
Если, например, было 0</B, а стало Count [1</B например]
if (Count > FColsCount)
{
FCols.Count = Count;

for (int i = FColsCount; i < Count; i++)
{
TCol *Buf = new TCol(this);
FCols.Memory[i] = Buf;
// -->>>
FColumns->Add()->Column = Buf;
}
}
...


Так всё вроде нормально работает (кроме случаев удаления элементов коллекции в дизайнере).

Стал добавлять свойства в мой TColumnItem - потомок TCollectionItem; в частности свойство Title : string; :

void __fastcall TColumnItem::SetTitle(AnsiString S)
{
 FCol->Title = S;
}


И так всё работает [в desine-time]. Зато при запуске приложения в ран-тайм, ошибка доступа к данным. Начал трассировать, оказывается, FCol = nil. Начал трассировать дальше, оказалась вообще ерунда какая-то...  TColumnItem сначала создаётся, потом даже вызывается его деструктор, потом...

Очень прошу помощи. Что я делаю не так?


 
DevilDevil ©   (2006-09-26 14:35) [1]

sorry за опечатку в тегах


 
DimaBr   (2006-09-26 15:11) [2]

не видно конструктора и описания класса.
1. что раньше - создаётся коллекция или назначаютсяколичество столбцов ?
2. что раньше в published  Column или ColsCount ?

> Теобходимо написать редактор столбцов.

?????


 
DevilDevil ©   (2006-09-26 15:18) [3]

> Теобходимо написать редактор столбцов.
?????


Необходимо иметь возможность в дизайн-тайм изменять Title, Width и др свойства столбца.

> 1. что раньше - создаётся коллекция или назначаются количество  столбцов ?

конструктор коллекции выполняется в конструкторе таблицы. Количество столбцов назначается... при изменении published свойства Таблица.ColsCount

> 2. что раньше в published  Column или ColsCount ?
ColsCount


 
DimaBr   (2006-09-26 16:24) [4]


> Необходимо иметь возможность в дизайн-тайм изменять Title,
>  Width и др свойства столбца.

Для этого достаточно иметь published свойтство типа TCollection, тогда в инспекторе у этого свойства появится "..." с окном для редактирования коллекции. Если вы хотите изменять ReadOnly свойство ColCount, то я бы написал так

   fColumns: TCollection;
   property Columns: TCollection read fColumns write fColumns;
   property ColCount: integer read GetColCount write SetColCount;

function TForm1.GetColCount: integer;
begin
 Result := fColumns.Count;
end;

procedure TForm1.SetColCount(const Value: integer);
begin
 while ColCount < Value do Columns.Add;
 while ColCount > Value do Columns.Delete(ColCount-1);
end;


 
DevilDevil ©   (2006-09-27 15:33) [5]

В приведённом тобой случае, что сохраниться в dfm и в каком порядке будет работать?


 
DimaBr   (2006-09-27 15:46) [6]


private
fColumns: TCollection;
published
  property Columns: TCollection read fColumns write fColumns;
  property ColCount: integer read GetColCount write SetColCount;

и не  дай бог наоборот


 
DevilDevil ©   (2006-09-27 15:49) [7]

А почему "write fColumns" а не SetColumns?


 
DimaBr   (2006-09-27 16:05) [8]

Можно и SetColumns


 
DevilDevil ©   (2006-09-27 16:14) [9]

непонятно. Чтобы все столбцы загрузились (т.е. были созданы, инициализированы свойства Width и Title) ищз dfm, вроде необходимо использовать TCollection.Assign() .

Недопонимаю... Недопонимаю.......


 
DimaBr   (2006-09-27 16:19) [10]

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


 
DevilDevil ©   (2006-09-27 16:29) [11]

мммм.....

Что и в какой последовательности должно следовать, чтобы все столбцы создались и инициализировались, чтобы свойство ColsCount тоже работало?

В каких случаях следует использовать, а в каких нет SomeObject.Assign() ? Чё то я запутался уже...


 
DevilDevil ©   (2006-09-27 17:19) [12]

Разве может быть такое???

У коллекции перекрываю методы Add и Delete, в которых вписываю ShowMessage() с аргументами "Add" и "Delete" соответственно. При добавлении и удалении элементов коллекции в дизайнере, никаких ShowMessage не вызывается. Из-за чего такое происходит?

P.S. Компонент перекомпилирован


 
DevilDevil ©   (2006-09-27 18:23) [13]

Когда коллекция грузится из dfm, она вызывает метод Add? Если да, то свойство ColsCount сохранять не надо - т.к. оно само примет нужное значение при загрузке dfm.


 
DimaBr   (2006-09-28 08:47) [14]


> У коллекции перекрываю методы Add и Delete,

Методы не виртуальны, как вы умудрились их перекрыть ?

> свойство ColsCount сохранять не надо

В принципе правильно.


 
DevilDevil ©   (2006-09-28 15:22) [15]

> DimaBr   (28.09.06 08:47) [14]
> Методы не виртуальны, как вы умудрились их перекрыть ?


ммм... в Си нет директивы override, там это делается автоматически (если естественно метод виртуальный).

А как тогда мне перехватить и правильно отреагировать на изменения коллекции в дизайнере?

P.S. Дима, во - первых мы с Вами тёски, во - вторых Вы может быть старше меня... Может всё таки на "ты" ? :)


 
DimaBr   (2006-09-28 15:32) [16]

В коллекции есть методы

procedure Update(Item: TCollectionItem); virtual; //
procedure Added(var Item: TCollectionItem); virtual; deprecated;
procedure Deleting(Item: TCollectionItem); virtual; deprecated;
procedure Notify(Item: TCollectionItem; Action: TCollectionNotification); virtual;

которые и можно перекрыть


 
DimaBr   (2006-09-28 15:36) [17]

То есть пишем свою коллекцию

TMyCollection = class(TOwnedCollection)
  protected
     procedure Update(Item: TCollectionItem);override;        
end;

procedure TMyCollection.Update(Item: TCollectionItem);
begin // возникает при изменении элемента коллекции в инспекторе

end;

и тогда
fColumns := TMyCollection.Create(self,TMyCollectionItem);


 
DevilDevil ©   (2006-09-28 16:45) [18]

перекрываю метод Added, вписываю ShowMessage("Added");

Достаточно странно: при добавлении, ShowMessage вызывается дважды. Аналогично в Ран-Тайм; при загрузке приложения, на три колонки - 6 вызовов  ShowMessage. Почему?

Как отследить, присвоено свойство при загрузке dfm или нет?

Позорный вопрос: за что отвечает директива deprecated ?


 
Ketmar ©   (2006-09-28 16:51) [19]

"deprecated" -- "устаревшее".


 
DimaBr   (2006-09-28 16:56) [20]


> Как отследить, присвоено свойство при загрузке dfm или нет?

не понял

deprecated - говорит о том, что использованая функция объявлена как устаревшая и рекомендуется использовать что-то новое


 
DevilDevil ©   (2006-09-28 17:50) [21]

> Как отследить, присвоено свойство при загрузке dfm или нет?
> не понял

Ну смотри. При вызове Added я должен произвести некоторые действия с оперативной памятью, добавить столбец, перерисовать таблицу.

Незнаю почему [ :) ], но мне не хочется перерисовывать таблицу, если свойство присвоено (или вызван метод, Added, например) в момент загрузки dfm. Таких загрузок много. На данный момент выполняется минимум 27 лишних перерисовок таблицы.

Почему метод Added дублируется?


 
DevilDevil ©   (2006-09-28 20:15) [22]

АААЛЕЕЕЛУУУЯЯ, ААЛЕЛУУУУЯ, АЛЕЕЕЕЛУЯ, АЛЕЛУЯ, АЛЕЛУЯ...

TCollection.Notify:

begin

  case
(Action) of:

    cnAdded     : MyAdding(Item);
    cnExtracting, cnDeleting  : MyDeleting(Item->Index);

  end;

end;


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


 
DimaBr   (2006-09-29 08:48) [23]

Для уменьшения количества отрисовок используем BeginUpdate - EndUpdate


 
DevilDevil ©   (2006-10-02 15:46) [24]

Снова вопросы.

Создал пока 2 свойства: Title : string и Width : integer;

Примечательно то, что если изменить эти своства в Object Inspector-е, то всё корректно сохранится в dfm. Если Object Inspector не использовать, то свойство не сохраняется.

Допустим ширина первого столбца равна 20 пикселей. Мышью изменяю ширину столбца до ста двадцати пикселей, запускаю - ширина почему-то равна 20 пикселей. Смотрю в Object Inspector; написано 120. Запускаю - опять 20. Опять захожу в Инспектор, кликаю в поле Width, нажимаю Enter, запускаю... Всё работает правильно...

Вопрос: Как заставить сохраниться в dfm?

Вопрос №2: При клике в шапке столбца, соответсвующий столбец должен открыться в Инспекторе Объектов. Как это реализовать?


 
DimaBr   (2006-10-02 16:20) [25]

1. Нужно сообщить дизайнеру что произошли изменения.

при перемещении колонки
if GetParentForm(self) > nil then
 if GetParentForm(self).Designer <> nil then
   GetParentForm(self).Designer.Modified;

2. Для этого вам придётся переписать половину VCL, по крайней мере свой ТСомponent, TControl и т д. Это реализовано в DevExpress, загляните.


 
DevilDevil ©   (2006-10-02 18:05) [26]

ВСЕМ спасибо ОГРОМНОЕ. В частности ДимеБр !!!

Вроде всё работает как надо...



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

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

Наверх




Память: 0.54 MB
Время: 0.025 c
15-1185249634
de.
2007-07-24 08:00
2007.08.19
Как удалить себя из списка?


15-1184935042
Ксюша
2007-07-20 16:37
2007.08.19
DELPHI+OUTLOOK


15-1184915044
Nic
2007-07-20 11:04
2007.08.19
Paradox : нужно ли ставить на компьютер BDE?


15-1184712286
Германн
2007-07-18 02:44
2007.08.19
Как молоды мы были, как искренне любили


2-1185121783
ququq
2007-07-22 20:29
2007.08.19
Приведение типов.