Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  14:01[Войти] | [Зарегистрироваться]
Ответ на вопрос № 83914

05-04-2025 00:42
Что-то не могу реализовать простейшее.
Есть TreeView, которое грузится из БД.
Добавляю новый узел, перезагружаю дерево (это касается только level = 1, поэтому не напряжно).
Хочу выделить (и раскрыть) узел, на котором пролизошло добавление.
Но почему-то код ниже не работает. Выделяется соседний узел.

i:=TV.Selected.Index;
  try
  // здесь должно быть добавление в базу записи,
  // которая потом будет дочерним узлом для выделенного
  // но пока ничего не добавляется, поэтому не должно влиять
  finally
  ReLoadTree; // очищает дерево и загружает повторно
  TV.Items[i].Selected:=true; // i равно сохраненному
  end;



С ItemId еще большая путаница.
Подскажите, как это реализовать.

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

08-04-2025 23:48 | Сообщение от автора вопроса
Очень большое спасибо.
Да, сам убедился, что с AbsoluteIndex тоже работает не всегда правильно.
Поэтому  сделал, как Вы посоветовали в предыдущем посте - стал использовать ID из базы, который хранится в структуре, привязанной к узлу.
Для небольшого количества поиск нужного узла по дереву никак не тормозит программу.

08-04-2025 13:29
>>>переделал на Selected.AbsoluteIndex. Теперь всё работает как ожидалось. Нет ли в таком подходе "подводных камней"?
  Смотря какую задачу, вы решаете.
  Вы используете подход, в котором привязываете "прикладные данные" к "индексу позиционирования" узла в дереве.
  Обычно же, используют другой подход. В "прикладных данных" выделяют уникальный идентификатор. И этот идентификатор добавляют к узлу дерева. Если дерево перезагружают (например, из БД), то позиционирование в дереве востанавливают по этому идентификатору. По нему же производится синхронизация данных из дерева TreeView и данных из БД.

08-04-2025 13:24
>>>переделал на Selected.AbsoluteIndex
  В моём первом посте закралась ошибка.
  Под ItemId, я подразумевал AbsoluteIndex. Но и это верно лишь отчасти. Поскольку, AbsoluteIndex это индекс в общем списке TreeView.Items, а не закреплённый "идентификатор узла".
 
>>>В результате экспериментов заметил какую-то закономерность
  Закономерность индексов в TreeView можно проследить с помощью следующих процедур:


//  TfvMain = class(TForm)
//    trvTree: TTreeView;

const
  cMaxItems = 5;
  cNodeName = 'Node_';

procedure TfvMain.TreeClear;
begin
  trvTree.Items.Clear
end;

procedure TfvMain.TreeInsert;
  var wNode, wNode2 :TTreeNode;
begin
  wNode := trvTree.Selected;
  wNode2 := trvTree.Items.Insert(wNode, '');
  NodeSetName(wNode2);
end;

procedure TfvMain.TreeLoad;

  procedure NodeSetName( aNode :TTreeNode);
  begin
    aNode.Text := cNodeName +
                    //индекс локальный, уникальный в ветке дерева TreeNode.Item[]
                  IntToStr(aNode.Index) + '_' +
                    //индекс глобальный, уникальный по всему дереву TreeView.Items[]
                  IntToStr(aNode.AbsoluteIndex) + '_' +
                    //дескриптор узла (win api), уникальный по всему дереву
                  IntToHex(Integer(aNode.ItemId), 8);
  end;

  var
    wNode, wNode2 :TTreeNode;
    i, j :integer;
begin
  with trvTree.Items do
  begin
    BeginUpdate;
    for i := 1 to cMaxItems do
    begin
      wNode := Add(nil, '');
      NodeSetName(wNode);
      for j := 1 to cMaxItems do
      begin
        wNode2 := AddChild(wNode, '');
        NodeSetName(wNode2);
        end;
      end;
    trvTree.FullExpand;
    EndUpdate;
    end;
end;

 
  Если, после выполнения TreeLoad, в середину дерева вставить новый элемент, то сдвинутся все AbsoluteIndex в TreeView.Items[] после этого элемента и Index в TreeNode.Item[] в локальной ветке, тоже после этого элемента.

08-04-2025 01:00 | Сообщение от автора вопроса
Спасибо за ответ.
При добавлении (удалении)узлов, я понимаю, что индексы должны меняться. Но в конкретном случае дерево не меняется.
В результате экспериментов заметил какую-то закономерность, но не стал анализировать, т.к. переделал на Selected.AbsoluteIndex.
Теперь всё работает как ожидалось. Нет ли в таком подходе "подводных камней"?

05-04-2025 09:57
>>>Хочу выделить (и раскрыть) узел, на котором произошло добавление. Но почему-то код ниже не работает. Выделяется соседний узел.
  Поясню на примере.
  Представьте, что у вас есть линейный массив, который вы загружаете значениями из БД. Вы отмечаете в массиве, например, элемент с № 5. И запоминаете этот №. Теперь вы перезагружаете содержимое массива из БД. А после этого вставляете новый элемент между элементами №3 и №4.
  Очевидно, что под № 5, в массиве будет элемент с другим содержимым, чем в первом случае. А нужный вам элемент, будет соседним с ним (№ 6).
 
  Возвращаясь к TreeView, можно сказать, что индекс i в TreeView.Items[i], это такой же аналог индекса в массиве. А ItemId - это уникальный идентификатор элемента. На практике, он реализован через авто-инкремент при добавлении нового элемента. Поэтому, когда вы перезагружаете TreeView из БД (т.е. сначала удаляете все элементы дерева, а затем их создаёте), значение ItemId элементов будет тоже новым.

>>>Подскажите, как это реализовать. 
  По теме вопроса, на этом сайте, есть статья: "DBTreeView своими руками".
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=488 

  Но на практике, обычно, пользуются уже готовыми компонентами. Например, в библиотеке Jedi есть компонент JvDBTreeView.

Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Однажды, в студеную зимнюю пору я из лесу вышел, был сильный ЧТО?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования