Перейти к содержанию
Fire Monkey от А до Я
  • 0

Список выделенных узлов в TTreeView


Frol

Вопрос

Опубликовано (изменено)

Добрый день в VCL можно было получить список выделенных узлов. Например с помощью 

TCustomTreeView.GetSelections(AList: TList)

можно было записать их в список. При этом сохранялись не только сами узлы, но и порядок в котором они выбирались.

Есть ли способ восстановить последовательность выделения в FM без танцев с бубнами? )))

Изменено пользователем Frol
опечатка

Рекомендуемые сообщения

  • 0
Опубликовано

все ручками делается очень примитивно и просто - один List и один обработчик клика
нет смысла такой функционал тащить в общий компонент

  • 0
Опубликовано

т.е. я создаю свой список и на момент клика по элементу добавляю или удаляю? Понятно. спасибо

  • 0
Опубликовано (изменено)

Не так все оказалось банально. Когда включен мультиселект в дереве, то могут возникать более сложные комбинации чем один убрали, второй записали. Может происходить накопление узлов в ссылке или мгновенный сброс накопленных. Кроме того выделение может происходить не только по клику мышкой, но и по нажатию стрелочки на клавиатуре. В некоторых ситуациях возможно появление дублирующих ссылок на узел в списке. Все это не сложно, просто требует какой-то аккуратности и проверок.

Для меня FireMonkey что-то совсем новое... Так-то оно все очень полезно даже... Но некоторые моменты ставят в тупик. 

В контексте данной задачи для тренировки написал процедуру которая обходит все узлы дерева и удаляет те, что являются IsSelected.

Деструктор выглядит так

Цитата

destructor TTestTreeViewItem.Destroy;
begin
  Parent := nil;//подсмотрел на этом форуме, пока не понимаю зачем это нужно
  inherited;
end;

деструктор вызывается таким образом

 

Цитата

procedure DelItem(Item:TTreeViewItem);
 begin
    if Item.IsSelected then FreeAndNil(Item);

после этого в моем понимании указатель на узел дерева должен быть NIL

После удаления узлов я прохожу цикл по списку и удаляю из него те, которым в нем уже не место

Собственно новый вопрос тут

Цитата

procedure TFMSelectedItemsList.DeSelectCheck;
var
  i: NativeInt;
  Item:TTreeViewItem;
  b:boolean;
  S:string;
begin
  for i := Count-1 downto 0 do
  begin
    Item:=Items[i];//почему-то удаленные узлы все равно есть
    b:=Assigned(Item);
    S:=Item.Text;
    b:=Item.IsSelected;
    if not Items[i].IsSelected then Delete(i);
  end;
end;

в моем понимании проверка Assigned(Item) для удаленного узла должна дать false. Но все узлы true. Даже удаленные

У удаленных нет текста, IsSelected=false, какие-то их проперти NIL... Но сам узел есть в памяти. Обращение к полям узла в данной процедуре не вызывает ошибку. как так?

Изменено пользователем Frol
  • 0
Опубликовано (изменено)

Up

почему после удаления объекта через FreeAndNil обращение к нему возможно?

Изменено пользователем Frol
  • 0
Опубликовано

дерево это условно список указателей

пусть item := tree[i]

FreeAndNil(item) === item.Free; item := nil;

в tree[i] как был старый указатель, так и есть. Если к нему обратиться, в лучшем случае будет ошибка. В худшем - что-то попортится и все упадет совсем.

 

Parent содержит ссылку на child поэтому перед тем как разрушить child, неплохо бы чтобы parent эту ссылку потерял, там вроде был механизм, что во время присваивания Parent, от старого Parent мы отцепляемся. Могу наврать.

В любом случае есть же штатный метод удаления узла, нужно просто посмотреть в код TreeView и найти его. Там все уже учтено.

  • 0
Опубликовано (изменено)

С точки зрения дерева удаление происходит корректно. Но какой-то сторонний наблюдатель, который знал адрес куда смотреть продолжает видеть там не Nil. Я могу в момент удаления узла из дерева принудительно удалить его и из списка. Но мне любопытно как так. В VCL такой метод сработал бы. Я вижу тут какую-то особенность FM, которую не понимаю. 

Я понял идею. Когда я создавал Item, то сперва создавал его, а потом прописывал уже созданному указатель на родителя. Попробую удалять item средствами родителя, хотя не уверен, что что-то поменяется: С точки зрения дерева удаление происходит корректно. Ну... или так кажется )))

Цитата

destructor TTestTreeViewItem.Destroy;
begin
  Parent := nil;//подсмотрел на этом форуме, пока не понимаю зачем это нужно
  inherited;
end;

чтобы разорвать связь с парентом этого не достаточно?

Изменено пользователем Frol
  • 0
Опубликовано

ну есть же исходники

procedure TCustomTreeView.RemoveObject(AObject: TFmxObject);
begin
  if (AObject is TTreeViewItem) and (TTreeViewItem(AObject).TreeView = Self) then
  begin
    TTreeViewItem(AObject).Parent := nil;
  end
  else
    inherited;
end;

вроде как достаточно

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...