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


Автор: Alix 8.11.2005, 09:48
Обыскал рунет, но так и не нашел описание того, как можно сделать перемещения элементов в TreeView вверх/вниз на позицию, влево/вправо (т.е. выше на каталог и поместить в нижний каталог).
Сам я это все сделал. Точнее пока только вверх/вниз. И оно работает. Но если один элемент переместить вверх/вниз опр. (притом фиксированное!) число раз, то вылетает Access Violation. А так ничего... работает... Но проблема в том, что я не могу найти откуда у этого violation'a "ноги растут"... Думал что это конфликт с обработчиками событий TreeView'a, но закоментировал их код, а ошибка все равно осталась.
Пожалуйста, напишите, как бы вы сделали перемещение элемента вверх/вниз (хотя бы это). Заодно в DRKB поместить можно будет smile В рунете этого точно нет...
Перемещать можно по-разному. Как способ предлагаю написать ф-ю Exchange(node1, node2 : TTreeNode), которая меняла бы соседние эл-ты местами. Соответственно функции:
Код
procedure MoveUp;
var
  node, prev : TTreeNode;
begin
  node := TreeView.Selected;
  if node = nil then
    exit;

  prev := node.getPrevSibling; //но не getPrev!!!
  if prev = nil then
    exit;

  Exchange(prev, node);
end;

procedure MoveDown;
var
  node, next : TTreeNode;
begin
  node := TreeView.Selected;
  if node = nil then
    exit;

  next := node.getNextSibling; //но не getNext!!!
  if next = nil then
    exit;

  Exchange(node, next);
end;

// ну и обработчик OnKeyDown или OnKeyUp TreeView'a с if key=VK_UP или т.п.

Автор: _hunter 8.11.2005, 12:28
код Exchange() привести не помешало бы...

Автор: Alix 8.11.2005, 15:50
Цитата(_hunter @ 8.11.2005, 12:28)
код Exchange() привести не помешало бы...

Цитата
Как способ предлагаю написать ф-ю Exchange(node1, node2 : TTreeNode), которая меняла бы соседние эл-ты местами.

Читайте внимательнее!

Автор: _hunter 8.11.2005, 16:04
Цитата
Сам я это все сделал. Точнее пока только вверх/вниз. И оно работает. Но если один элемент переместить вверх/вниз опр. (притом фиксированное!) число раз, то вылетает Access Violation.

из чего я делаю вывод что код есть. его я и просил.

или под
Цитата
Как способ предлагаю написать ...

следует понимать приглашение для всех желающих написать эту функцию?

Автор: Alix 9.11.2005, 09:10
Поясняю.
Да, код есть. Но есть и непонятные глюки. Поэтому я прошу тех, кто может, написать всего одну очень простую функцию Exchange.
Свой код я не привожу по той причине, что, быть может, у данной задачи есть несколько путей решения и я не хочу, чтобы другие, посмотрев на мой код, начали искать решение в том же направлении, где его искал я. Тогда, может быть, появятся решения другого типа нежели у меня и, может быть, с ним не будет никаких глюков.
Хотя если вы будете настаивать, свой код я выложить могу. Благо это задача copy/paste...

Автор: _hunter 9.11.2005, 12:01
код выкладывай ( заодно о своих ошибках узнаеш )

а решение зависит от того, нужно ли детей ноды переносить.

Автор: Alix 9.11.2005, 13:42
Цитата
а решение зависит от того, нужно ли детей ноды переносить.

Разумеется!

Ладно. Уломал. Вот код:
Код
// вот эту фунцию я взял с какого-то форму. Сорри если что... :)
procedure MoveChildren(SrcNode, DestNode: TTreeNode);
begin
     if (SrcNode = nil) or (DestNode = nil) or
        (SrcNode = DestNode) or DestNode.HasAsParent(SrcNode) then exit;
     while SrcNode.Count > 0 do
       SrcNode.Item[0].MoveTo(DestNode, naAddChild);
end;

function Exchange(node1, node2 : TTreeNode) : boolean;
var
  node : TTreeNode;

begin
  Result := true; // ну мне это надо было...
  node := TreeView.Items.InsertObject(node1, node2.Text, node2.Data);

  MoveChildren(node2, node);
  node2.Free;
  node.Collapse(false);
  node1.Collapse(false);
end;

Да! Забыл здесь написать (а так это есть). В функциях MoveUp/Down оисанных выше вызов Exchange обрамлен следующим кодом:
Код
TreeView.Items.BeginUpdate;
// Exchange here...
TreeView.Items.EndUpdate;

Автор: Alexeis 10.11.2005, 10:16
Вот такой код позволяет перетаскивать элементы Treeview

Код

type
  TForm1 = class(TForm)
    Button1: TButton;
    TreeView1: TTreeView;
    TreeView2: TTreeView;
    procedure Button1Click(Sender: TObject);
    procedure TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure MoveNode(TargetNode, SourceNode: TTreeNode);
  end;
  
var
  Form1: TForm1;


implementation

{$R *.dfm}

  //Dragmode := mautomatic

procedure TForm1.Button1Click(Sender: TObject);
begin
 TreeView1.SetFocus;
end;

procedure TForm1.MoveNode(TargetNode, SourceNode: TTreeNode);
var
  nodeTmp : TTreeNode;
  i       : Integer;
begin
  with TreeView1 do
  begin
    nodeTmp := Items.AddChild(TargetNode, SourceNode.Text);
    for i := 0 to SourceNode.Count - 1 do
    begin
      MoveNode(nodeTmp, SourceNode.Item[i]);
    end;
  end;
end;


procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
  TargetNode, SourceNode: TTreeNode;
begin
  with TreeView1 do
  begin
    TargetNode := GetNodeAt(X, Y); // Get target node
    SourceNode := Selected;

    if TargetNode = nil
    then
      begin
        TreeView1.Items.Add(nil, SourceNode.Text);
        SourceNode.Free;
        EndDrag(False);
        Exit;
      end;

    if TargetNode = SourceNode
    then
      begin
        EndDrag(False);
        Exit;
      end;

    MoveNode(TargetNode, SourceNode);
    SourceNode.Free;
  end;
end;

procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
  if (Sender = TreeView1) then // If TRUE than accept the draged item
  begin
    Accept := True;
  end;

end;

Автор: Albinos_x 10.11.2005, 11:36
alexeis1
я думаю ему нужно не передаскивание, а именно перемещение

Автор: Quadr0 10.11.2005, 13:56
...

Автор: Alexeis 10.11.2005, 14:32
Quadr0
Сортировка вроде не работает,
а внутренние элементы дерева(листья)
перемещаются неверно (перескакивают с уровня на уровень)

Автор: Quadr0 10.11.2005, 14:52
...

Автор: Alexeis 10.11.2005, 15:02
Quadr0
Ввел весь алфовит при нажатии на кнопку
"сортировка по возрастанию", "сортировка по убыванию"
ноль эмоций

компилировал в delphi7

Автор: Alix 10.11.2005, 15:19
Well... smile
Спасибо, Quadr0. Сортировка мне даром не была нужна, правда, но смысл ясен.
Увидел naInsert - не поверил, что оно есть, полез в хелп - точно есть. Я просто уже смотрел moveTo, но не заметил там naInsert и долго, помниться, еще ругался, почему везде одни только naAdd'ы smile .
Еще мне не нужен был переход к родителю - это уже отдельные функции. В итоге мой код:
Код
procedure MoveUp;
var
  node : TTreeNode;
  prev : TTreeNode;

begin
  node := TreeView.Selected;
  if node = nil then exit;

  prev := node.getPrevSibling;
  if prev = nil then exit; // не надо переходить к родителю. Так, например, в The Bat'e сделано.

  TreeView.Items.BeginUpdate;
  node.MoveTo(prev, naInsert);
  TreeView.Selected := node;
  TreeView.Items.EndUpdate;
end;

procedure MoveDown;
var
  node : TTreeNode;
  next : TTreeNode;

begin
  node := TreeView.Selected;
  if node = nil then exit;

  next := node.getNextSibling;
  if next = nil then exit;

  TreeView.Items.BeginUpdate;
  next.MoveTo(node, naInsert);
  TreeView.Selected := node;
  TreeView.Items.EndUpdate;
end;

Глюков тоже больше нет smile. Странно, почему прошлый код вызывал Access Violation...

Автор: Quadr0 10.11.2005, 15:58
...

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