Delphi: Решение проблем с фокусом и удалением узлов в TVirtualStringTree
При работе с компонентом TVirtualStringTree в Delphi может возникнуть необходимость изменить фокус после удаления узла и инициировать определенные реакции на это изменение. В данной статье мы рассмотрим, как решить эту проблему, а также поговорим о более элегантном способе изменения фокуса без нежелательных последствий.
Описание проблемы
У нас есть компонент типа TVirtualStringTree (далее VST), содержащий узлы в виде списка, то есть все узлы находятся на одном уровне. При удалении узла с помощью метода DeleteNode мы хотим изменить фокус и инициировать определенные реакции, например, установить свойство Enabled кнопки. Для этого мы используем события OnFreeNode и OnFocusChanged:
procedure TMyForm.VSTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
NewFocus: PVirtualNode;
begin
NewFocus := VST.GetNext(Node);
if not Assigned(NewFocus) then
NewFocus := VST.GetPrevious(Node);
if Assigned(NewFocus) then
begin
VST.FocusedNode := NewFocus;
VST.Selected[NewFocus] := True;
end;
end;
procedure TMyForm.VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
begin
btn1.Enabled := Assigned(Node);
end;
Однако при закрытии формы с помощью кнопки "Отмена" (форма открывается методом ShowModal) узлы освобождаются, инициируется событие VSTFocusChanged, что приводит к исключению из-за отсутствия кнопки. Конечно, мы можем проверить, назначена ли кнопка, но есть ли более элегантное решение для изменения фокуса после удаления узла без этого нежелательного эффекта (и без других нежелательных эффектов)?
Альтернативный ответ:Always having a node selected
Существует встроенный способ всегда иметь выделенный узел. Удалите свой код из этих событий и включите опцию __toAlwaysSelectNode__ в набор опций TreeOptions.SelectionOptions (например, включите ее в IDE). Комментарий по этой опции гласит:
Если этот флаг установлен в True, компонент TVirtualStringTree пытается всегда иметь выделенный узел.
Это включает в себя удаление узла.
Как безопасно обновить состояние включения внешнего контрола из события VT?
Проблема, с которой вы столкнулись, заключается в том, что вы вручную фокусировались на узле из события OnFreeNode, что в свою очередь инициировало событие OnFocusChanged. И поскольку узлы также освобождаются, когда контроль distrut, а кнопка была разрушена раньше, вы пытались получить доступ к разрушенному контролю. Чтобы избежать этого в будущем, вы можете использовать RTL actions, так как есть много событий, которые VT запускает, даже когда сигнализируется состояние csDestroying (включая событие OnStructureChange), и действия - это один безопасный workaround.
Ниже приведен пример кода, который должен работать безопасно (я не фанат события OnUpdate действия):
procedure TMyForm.VSTStructureChange(Sender: TBaseVirtualTree; Node: PVirtualNode;
Reason: TChangeReason);
begin
{ ActionDeleteNode назначена свойству Action кнопки; SelectedCount - это немного параноидально здесь, потому что если вы используете опцию toAlwaysSelectNode, по крайней мере, один узел всегда должен быть выделен, поэтому RootNodeCount > 0 могло бы сделать то же самое здесь }
ActionDeleteNode.Enabled := Sender.SelectedCount > 0;
end;
Без RTL actions вы можете безопасно обновить состояние кнопки, например, сразу после выполнения действия, например, после удаления узла:
Но с этим вы можете выйти из синхронизации и написать больше кода. Поэтому использование RTL actions - это то, что я бы предпочел.
Заключение
В этой статье мы рассмотрели проблему изменения фокуса после удаления узла в TVirtualStringTree и возможные решения. Мы узнали, как всегда иметь выделенный узел, а также как безопасно обновить состояние внешнего контрола из события VT. Используя подход, описанный в этой статье, вы сможете эффективно работать с компонентом TVirtualStringTree в Delphi, не сталкиваясь с нежелательными эффектами.
В статье рассматривается проблема фокусировки и удаления узлов в компоненте `TVirtualStringTree` в Delphi и способы ее решения.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.