-
Пишу наследника TTreeView и хочу сделать так, чтобы при добавлении нодов создавался экземпляр наследника TTreeNode . Сам дошел до того, что надо переписать метод TTreeView.CreateNode , т.е. скрыть его. Класс нода, в принципе можно задавать в OnCreateNodeClass , но как-то мне кажется нехорошо иметь в компоненте обработчик события. Вопрос в следующем: нет ли другого способа дать понять TTreeView , ноды какого класса ему создавать, кроме двух вышеоуказанных? И еще - что еще надо учесть, если я все-таки скрою TTreeView.CreateNode . Т.е. какие еще методы надо при этом перекрыть/скрыть?
-
> т.е. скрыть его Не скрыть, а перекрыть. Метод виртуальный. Специально для сабжа и предназначен. > нехорошо иметь в компоненте обработчик события. Не просто нехорошо, а вообще недопустимо. Пользователь компонента имеет полное право назначить свой обработчик, и тогда компонент работать перестанет. > нет ли другого способа Зачем? Разве недостаточно того, что уже есть? > какие еще методы надо при этом перекрыть/скрыть? Никакие.
function TMyTreeView.CreateNode: TTreeNode; var
LClass: TTreeNodeClass;
begin
LClass := TMyTreeNode; if Assigned(OnCreateNodeClass) then
OnCreateNodeClass(Self, LClass);
Result := LClass.Create(Items);
end;
-
> function TMyTreeView.CreateNode: TTreeNode; // override > var > LClass: TTreeNodeClass; > begin > LClass := TMyTreeNode; // Это и будет Ваш класс по умолчанию. > > if Assigned(OnCreateNodeClass) then > OnCreateNodeClass(Self, LClass); > Result := LClass.Create(Items); > end; >
да, это я и имел в виду. это никак не отличается от скрытия, поскольку не вызывается метод предка.
Спасибо за информацию.
-
Оказалось все не так просто :( Нужен еще наследник TTreeNodes , который бы знал, какой класс имеют ноды. Иначе теряется смысл всей этой кутерьмы :) Т.е. сейчас я перекрыл CreateNode , но при попытке сделать что-нибудь вроде MyTreeView.Items[1].MyNewProperty := x; Получаю сообщение о том, что MyNewProperty - неизвестный идентификатор. Что, в общем то, естественно, т.к. у TTreeNode такого свойства нет.
-
придется, похоже, еще и геттер TTreeNodes.Item скопировать
-
> umbra > это никак не отличается от скрытия От скрытия это отличается как раз самым коренным образом. И вызов метода предка (или НЕ вызов) тут абсолютно ни при чем. TMyTreeNode(MyTreeView.Items[1]).MyNewProperty := x; И все будет работать. Насчет геттера - если он виртуальный или динамический, то все будет ОК. Но если он статический, то ПЕРЕкрыть его не удастся, а удастся именно ЗАкрыть. А этого делать нельзя, потому что у пользователя компонента запросто могут возникать баги.
-
> А этого делать нельзя, потому что у пользователя компонента > запросто могут возникать баги.
Да ну. Вот TComponentList закрывает методы TObjectList и не жужжит. :)
-
> TMyTreeNode(MyTreeView.Items[1]).MyNewProperty := x; > И все будет работать.
это-то понятно > От скрытия это отличается как раз самым коренным образом. > И вызов метода предка (или НЕ вызов) тут абсолютно ни при > чем.
а чем в данном конкретном случае это отличается от объявления function CreateNode: TTreeNode; reintroduce; virtual; ?
-
> function CreateNode: TTreeNode; reintroduce; virtual;
Ты тут переопределил вирт. метод предка и снова объявил его виртуальным. Похоже на бред. Я вообще не могу представить зачем такое делать.
-
Все что тебе надо сделать, «чтобы при добавлении нодов создавался экземпляр наследника TTreeNode» перекрыть CreateNode. Вот так: function CreateNode: TTreeNode; override; function T???TreeView.CreateNode: TTreeNode;
var
LClass: TTreeNodeClass;
begin
LClass := TTreeNode;
if Assigned(FOnCreateNodeClass) then
FOnCreateNodeClass(Self, LClass);
Result := LClass.Create(Items);
end; И надо еще будет соответственно сделать аналог TTVCreateNodeClassEvent , который принимает классы не младше твоего.
-
Забыл исправить. function T???TreeView.CreateNode: TTreeNode;
var
LClass: TTreeNodeClass;
begin
LClass := T???TreeNode;
if Assigned(FOnCreateNodeClass) then
FOnCreateNodeClass(Self, LClass);
Result := LClass.Create(Items);
end;
-
> Ты тут переопределил вирт. метод предка и снова объявил > его виртуальным. Похоже на бред.
а так я практически скопировал код метода предка и вставил в свой метод. Тоже не верх элегантности. Зато хоть понятно, что это как бы совершенно новый метод, не опирающийся, типа, на старый :)
-
> Тоже не верх элегантности. Зато хоть понятно, что это как > бы совершенно новый метод, не опирающийся, типа, на старый > :)
Это, как бы сказать то
, эти директивы это не комментарии, они кое-что значат. > а так я практически скопировал код метода предка и вставил > в свой метод.
Ну и нет в этом ничего страшного. Это нормально в данном случае. Это правильное решение которое и имел ввиду разработчик TCustomTreeView делая метод CreateNode виртуальным. Я бы на твоем сместе от TCustomTreeView отнаследовался бы, чтобы с событием TTVCreateNodeClassEvent правильно расправится.
-
пришел к выводу, что без полного копирования класса TCustomTreeView в свой модуль невозможно создать его полноценного наследника, использующего наследника TTreeNode . Потому как в проекте, ипользующем контрол-наследник, все равно придется явно приводить тип нодов к нужному.
-
Ты че. Тебе надо написать наследников TCustomTreeView, TTreeNodes, TTreeNode.
В них тебе надо перекрыть 1(один) CreateNode и 1(один) CreateNodes и свойства Items.
Вот и все.
-
Тебе для того и вирт методы сделали, чтобы перекрывать их, а ты весь модулькопировать собрался, а потом говоришь, что 4 строки из [10] это некрасиво
-
-
> 2. Вот это посмотри:
Ты хочешь сказать, что я должен еще и о тех, кто хакает думать? Или ты имеешь ввиду, что Borland, закрывшый в методы в TComponentList и аналогах идиот? Чукча не читатель?Что непононятно, поясни?
-
> Kolan © (07.04.08 18:42) [17]
> Ты хочешь сказать, что...
Я уже сказал (в [5]) и повторяю: попытка "перекрытия" статических методов предка чревата неоднозначностью поведения и соответствующими багами. Примеры см. в ветке по ссылке и хаки тут ни при чем.
> Что непононятно, поясни?
Поясняю: ты эту ветку не читал.
-
Так предложи решение сабжа. Или ты считаешь, что скопировать к себе все TCustomTreeVeiw лучше чем закрыть геттеры?
|