Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Удаление в дереве


Автор: Akella 13.12.2005, 08:58
В дереве можно выделить несколько веток (правда выделение мышкой проблемное), так вот, как удалить выделенные ветки? smile

smile

Автор: Albinos_x 13.12.2005, 11:32
так не прокатывает?
Код
...
TreeView1.Selected.Delete;
...

Автор: Akella 13.12.2005, 11:56
мне нужно удалить не один, а несколько выделенных, возможно, что выделенных не подряд узлов.
Повторюсь, что нужет пример удаления выделенных (не подряд) узлов в дереве.

Автор: _hunter 13.12.2005, 12:13
примерно так:
for ( int item = 0; item < treeView->SelectionCount; item++ )
treeView->Items->Delete(treeView->Selections[item]);

Автор: Akella 13.12.2005, 12:31
вечером попробую
Добавлено @ 12:33
только в Delphi, наверное компилятор заставит что-то подставить, типа:

TreeView1.Items[index:integer].Delete

?? и что подставить вместо индекса?

Автор: Snowy 13.12.2005, 12:43
Код

for i:=0 to TreeView1.SelectionCount-1 do
  TreeView1.Selections[i].Delete;

Автор: Albinos_x 13.12.2005, 12:52
наверно так:
Код
...
var i:integer;
begin
for i:=0 to TreeView1.SelectionCount do
    TreeView1.Selected.Item[i].Delete;
...

Автор: _hunter 13.12.2005, 12:58
щас проверил
treeView.Items.Delete()
работает

Автор: Albinos_x 13.12.2005, 13:00
упс ... когда писал предыдущего поста не было... smile

Автор: Snowy 13.12.2005, 13:18
Я не проверял, но вероятно нужна будет защина на случай, если в списке выделенных есть подузлы, выделенного узла.
При удалении узла - удаляются все подузлы.
Так что есть вероятность, что мы попытаемся удалить уже несуществуюшую ветку.
Вероятно так будет корректней:
Код

while TreeView1.Selected<>nil do begin
  TreeView1.Selected.Delete;
  Application.ProcessMessages;
end;

Автор: Akella 26.12.2005, 13:14
Snowy
Цитата(Snowy @ 13.12.2005, 12:43)
1:
2:

for i:=0 to TreeView1.SelectionCount-1 do
  TreeView1.Selections[i].Delete;


List index is out of bounds smile

Добавлено @ 13:16
Цитата(Snowy @ 13.12.2005, 13:18)
Я не проверял, но вероятно нужна будет защина на случай, если в списке выделенных есть подузлы, выделенного узла.
При удалении узла - удаляются все подузлы.
Так что есть вероятность, что мы попытаемся удалить уже несуществуюшую ветку.
Вероятно так будет корректней:

код Pascal/Delphi
1:
2:
3:
4:

while TreeView1.Selected<>nil do begin
  TreeView1.Selected.Delete;
  Application.ProcessMessages;
end;

удаляются все!!! ветви из дерева, но радует, что без ошибок
Добавлено @ 13:18
Цитата(_hunter @ 13.12.2005, 12:58)
щас проверил
  treeView.Items.Delete()ж;
работает


[Error] uMain.pas(499): Not enough actual parameters

Автор: _hunter 26.12.2005, 13:48
так там ноду указать нужно:
treeView.Items.Delete(treeView.Selections[0]);
+ возможно treeView.Items.BeginUpdate() перед удалением вызвать нужно ( чтобы переиндексацию не проводить )

Автор: Snowy 26.12.2005, 15:59
Цитата(dsergey @ 26.12.2005, 13:14)
List index is out of bounds

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

var
  i: integer;
  lst: TList;
begin
  lst:=TList.Create;
  for i:=TreeView1.SelectionCount-1 downto 0 do
    lst.Add(TreeView1.Selections[i]);
  for i:=0 to lst.Count-1 do
    TTreeNode(lst[i]).Delete;
  lst.Free;
end;

Автор: Quadr0 26.12.2005, 23:58
...

Автор: Snowy 27.12.2005, 10:09
Цитата(Quadr0 @ 26.12.2005, 23:58)
Работает без запинок.

В том-то и проблема, что с запинками.
Только что проверил - если мы выделяем подузлы, то удаляет лишнее.
Все дело в волшебных пузырьках, т.е. в подузлах.
Я уже по разному пробовал - Selections модифицируется и вся логика начинает хромать на 3 ноги.
Вот, как надежный вариант - сделал слепок состояния, а потом прибиваю по состоянию на исходный момент, чтобы уйти от этой динамики.

Автор: Girder 27.12.2005, 11:22
Код
var i:integer;
function Ch_Par(T:TTreeNode):Boolean;
begin
 Result:=false;
 if T=nil then exit;
 Result:=T.Selected;
 if Result=false then Result:=Ch_Par(T.Parent);
end;
begin
 for i:=TreeView1.SelectionCount-1 downto 0 do
  if Ch_Par(TreeView1.Selections[i].Parent)=false then TreeView1.Selections[i].Delete;
end;

Автор: Akella 27.12.2005, 11:24
Так что, получается, что "нормально" никак нельзя удалить выделенные узлы, что-ли?

Автор: Akella 27.12.2005, 14:04
Girder

вроде без ошибок, но удаляет даже если ничего не выделенно, поковыряю

Автор: Snowy 27.12.2005, 14:12
Цитата(dsergey @ 27.12.2005, 14:04)
Girder
вроде без ошибок, но удаляет даже если ничего не выделенно

Сыпется. List index of bounds...
Добавлено @ 14:13
И бывает удаляет ненужное.

Автор: Girder 27.12.2005, 17:12
Код
 TreeView1.Select(TreeView1.Items.AddChild(nil,'sdf'),[ssCtrl]);
 while (TreeView1.SelectionCount>1) do
  TreeView1.Selections[TreeView1.SelectionCount-1].Delete;
 TreeView1.Selected.Delete;


PS: msControlSelect=true

Автор: Akella 29.12.2005, 13:45
Girder, класс с меня +

этот код с форума на исходниках, вроде тоже работает, но размер кода smile
Код

function HasAsParent(Node, PotentialParent: TTreeNode): Boolean;
begin
  Node := Node.Parent;
  while (Node <> nil) and (Node <> PotentialParent) do
    Node := Node.Parent;
  Result := Node = PotentialParent;
end;

procedure DeleteAllSelected_Jack128(TV: TTreeView);
var
  List: TList;
  I, J: Integer;
  F: boolean;
begin
  List := TList.Create;
  try
    List.Capacity := TV.SelectionCount;
    for I := 0 to TV.SelectionCount - 1 do
    begin
      // Ищем, может кого из родителей уже занесли в список на выбывание ;)
      F := False;
      for J := 0 to List.Count - 1 do
      begin
        F := HasAsParent(TV.Selections[I], TTreeNode(List[J]));
        if F then Break;
      end;
      if F then // Родителя удалят, так что текущий узел удалять не нужно
        Continue;
      // Теперь нужно удалить всех детей, которые уже были записаны в список
      for J := List.Count - 1 downto 0 do
        if HasAsParent(TTreeNode(List[J]), TV.Selections[I]) then
          List.Delete(J);
      // Вот теперь можно со спокойной душей добовлять узел в список..
      List.Add(TV.Selections[I])
    end;
    for I := 0 to List.Count - 1 do
      TTreeNode(List[I]).Delete;
  finally
    List.Free;
  end;
end;

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)