Форум поддержки пользователей LibreOffice, Apache OpenOffice

Главная категория => Base => Тема начата: iyugov от 5 мая 2021, 18:55

Название: Хранение и отображение иерархической (древовидной) структуры объектов
Отправлено: iyugov от 5 мая 2021, 18:55
Есть необходимость хранить в базе данных иерархию объектов - тем учебных заданий. У каждой темы может быть произвольное количество подчинённых тем, у тех - тоже подчинённые темы и так далее. Колчество уровней подчинения не ограничено.

Для хранения тем в базе данных создана таблица со следующими полями:
1) id - ключ;
2) title - название объекта;
3) parent_id - id объекта из этой же таблицы.
Для id и parent_id создана связь.

Не могу понять, как организовать просмотр этой структуры на форме Base. Сейчас там форма с субформой, где для каждой темы видны непосредственно подчинённые темы (см. 1-й скриншот). Но такой формой в большинстве случаев совершенно невозможно пользоваться. Очень желательно именно древовидное отображение тем (пример - скриншот №2). Можно ли получить в LibreOffice Base древовидное отображение данных из таблицы? Искал подобие TreeView, но в формах Base такой элемент управления вроде бы недоступен.

Прошу форум помочь с отображением иерархических данных на форме.
Название: Re: Хранение и отображение иерархической (древовидной) структуры объектов
Отправлено: eeigor от 6 мая 2021, 06:36
На вашем рисунке показан пример элемента управления "Hierachical Grid" (иерархическая сетка). Заполняется как TreeView (рекурсивно при неограниченной вложенности). Есть ли здесь такой (от третьей стороны)?..
Есть служба: UnoControlGridModel. Но это для диалоговых окон.
XGridDataModel   Задает XGridDataModel, предоставляющий иерархические данные.

Upd1
Link (https://wiki.openoffice.org/wiki/Going_further_with_Dialog_and_Component#The_New_Tree_Control)

В MS Access я размещал обычный TreeView прямо на форме и синхронизировал его с записью в главной форме. Приемлемо вполне. Кстати, там можно было и переподчинять узлы методом Drag&Drop.
Есть там и иерархический Recordset (ADODB) с своей SQL конструкцией (оператор SHAPE)... Тоже интересно познакомиться с тем, как эти вопросы решаются здесь...
Возможно, вам надо реализовать работу со структурой в диалоговом окне (просмотр и выбор), а все поля иметь в штатной форме (ввод данных). Текущий узел в диалоговом окне можно синхронизировать с записью в форме. Как заполнить дерево – ссылка выше. Только рекурсивно. Загружать первый дочерний уровень, а его узлам, в свою очередь, подцеплять фиктивный (dummy) узел для каждой вложенной ветви (чтобы отображался знак "плюс"); при разворачивании такого узла производится загрузка по аналогии требуемой ветви. Если записей до 1000, то можно загрузить всё дерево сразу (без фиктивных узлов).
В LO я этого всего ещё не делал...

Upd2
Обратите внимание на свойство "hasChildsOnDemand" (если True, хоть и ChildCount = 0, то ветвь в источнике не пустая). Я так понимаю, что не надо цеплять фиктивный узел: достаточно задать свойство. Много всего...
http://www.openoffice.org/api/docs/common/ref/com/sun/star/awt/tree/XTreeExpansionListener.html#requestChildNodes
Поделитесь результатами

Upd3
Link (https://wiki.openoffice.org/wiki/Treecontrol#XTreeWillExpandListener)
Название: Re: Хранение и отображение иерархической (древовидной) структуры объектов
Отправлено: iyugov от 6 мая 2021, 22:08
Сделал форму topic_selection, диалог, заполнение дерева (пока тупенько и без рекурсии).
Видно, что дерево заполняется медленно (там 500+ узлов), но это пока не главная проблема, не связываюсь с OnDemand.
Вопросы такие:
- как возвращать из диалога значение выбранного узла?
- можно ли закрывать диалог при double-click на узле?

Пока непонятно, насколько удобно будет этим пользоваться.
Название: Re: Хранение и отображение иерархической (древовидной) структуры объектов
Отправлено: eeigor от 6 мая 2021, 22:54
Это очень замедляет:
ReDim Preserve Nodes(N...)
Сделайте запрос к БД и, оперируя точными значениями, инициализируйте массив сразу.
Я, правда, не понял смысла этого:
      If UBound(Nodes()) = N Then
         If N < 1024 Then
            ReDim Preserve Nodes(N * 2)
         Else
            ReDim Preserve Nodes(N + 1024)
         End If
      End If

If you are interested in knowing when the selection changes implement a ::com::sun::star::view::XSelectionChangeListener and add the instance with the method ::com::sun::star::view::XSelectionSupplier::addSelectionChangeListener(). You than will be notified for any selection change.
Или это (надо посмотреть):
getNodeForLocation   Returns the node at the specified location.

MsgBox(oTreeCtrl.getSelection.getDisplayValue())

Link (http://www.openoffice.org/api/docs/common/ref/com/sun/star/awt/tree/XTreeControl.html)

На оба ваши вопроса даю (чисто умозрительно) положительные ответы. Но теперь вы ведущий, а мы наблюдатели.
Думаю, что путь выбран правильно.
Цитата: iyugov от  6 мая 2021, 22:08Пока непонятно, насколько удобно будет этим пользоваться.
Удобно. Окно диалога с деревом можно и не закрывать, если сделать его соответствующего размера (в зависимости от длины наименований).

Вам ещё один пример в помощь (прикреплен). Загружает дерево каталогов молниеносно. Выполните процедуру Main и выберите папку где-то верхнего уровня.


Upd:
Обратите внимание на события мыши (mousePressed, щелчки мыши тоже определяются: см. здесь (https://forumooo.ru/index.php/topic,8656.msg58381.html#msg58381)), а также событие mouseDragged (перетаскивание).
Не отформатировано. Примеров использования нет. Я это вижу впервые...

__ com.sun.star.awt.tree.XTreeEditListener __

  _ Events watched by this Listener _
disposing                                                  com.sun.star.lang.XEventListener
nodeEditing                                                com.sun.star.awt.tree.XTreeEditListener
nodeEdited                                                 com.sun.star.awt.tree.XTreeEditListener

  _ Methods using this Listener as a parameter _    ( nothing to display )


__ com.sun.star.awt.tree.XTreeExpansionListener __

  _ Events watched by this Listener _
disposing                                                  com.sun.star.lang.XEventListener
requestChildNodes                                          com.sun.star.awt.tree.XTreeExpansionListener
treeExpanding                                              com.sun.star.awt.tree.XTreeExpansionListener
treeCollapsing                                             com.sun.star.awt.tree.XTreeExpansionListener
treeExpanded                                               com.sun.star.awt.tree.XTreeExpansionListener
treeCollapsed                                              com.sun.star.awt.tree.XTreeExpansionListener

  _ Methods using this Listener as a parameter _    ( nothing to display )


__ com.sun.star.awt.XFocusListener __

  _ Events watched by this Listener _
disposing                                                  com.sun.star.lang.XEventListener
focusGained                                                com.sun.star.awt.XFocusListener
focusLost                                                  com.sun.star.awt.XFocusListener

  _ Methods using this Listener as a parameter _    ( nothing to display )


__ com.sun.star.awt.XKeyListener __

  _ Events watched by this Listener _
disposing                                                  com.sun.star.lang.XEventListener
keyPressed                                                 com.sun.star.awt.XKeyListener
keyReleased                                                com.sun.star.awt.XKeyListener

  _ Methods using this Listener as a parameter _    ( nothing to display )


__ com.sun.star.awt.XMouseListener __

  _ Events watched by this Listener _
disposing                                                  com.sun.star.lang.XEventListener
mousePressed                                               com.sun.star.awt.XMouseListener
mouseReleased                                              com.sun.star.awt.XMouseListener
mouseEntered                                               com.sun.star.awt.XMouseListener
mouseExited                                                com.sun.star.awt.XMouseListener

  _ Methods using this Listener as a parameter _    ( nothing to display )


__ com.sun.star.awt.XMouseMotionListener __

  _ Events watched by this Listener _
disposing                                                  com.sun.star.lang.XEventListener
mouseDragged                                               com.sun.star.awt.XMouseMotionListener
mouseMoved                                                 com.sun.star.awt.XMouseMotionListener

  _ Methods using this Listener as a parameter _    ( nothing to display )


__ com.sun.star.awt.XPaintListener __

  _ Events watched by this Listener _
disposing                                                  com.sun.star.lang.XEventListener
windowPaint                                                com.sun.star.awt.XPaintListener

  _ Methods using this Listener as a parameter _    ( nothing to display )


__ com.sun.star.awt.XWindowListener __

  _ Events watched by this Listener _
disposing                                                  com.sun.star.lang.XEventListener
windowResized                                              com.sun.star.awt.XWindowListener
windowMoved                                                com.sun.star.awt.XWindowListener
windowShown                                                com.sun.star.awt.XWindowListener
windowHidden                                               com.sun.star.awt.XWindowListener

  _ Methods using this Listener as a parameter _    ( nothing to display )


__ com.sun.star.lang.XEventListener __

  _ Events watched by this Listener _
disposing                                                  com.sun.star.lang.XEventListener

  _ Methods using this Listener as a parameter _    ( nothing to display )


__ com.sun.star.util.XModeChangeApproveListener __

  _ Events watched by this Listener _
disposing                                                  com.sun.star.lang.XEventListener
approveModeChange                                          com.sun.star.util.XModeChangeApproveListener

  _ Methods using this Listener as a parameter _    ( nothing to display )


__ com.sun.star.util.XModeChangeListener __

  _ Events watched by this Listener _
disposing                                                  com.sun.star.lang.XEventListener
modeChanged                                                com.sun.star.util.XModeChangeListener

  _ Methods using this Listener as a parameter _    ( nothing to display )


__ com.sun.star.view.XSelectionChangeListener __

  _ Events watched by this Listener _
disposing                                                  com.sun.star.lang.XEventListener
selectionChanged                                           com.sun.star.view.XSelectionChangeListener

  _ Methods using this Listener as a parameter _    ( nothing to display )

Updated
Название: Re: Хранение и отображение иерархической (древовидной) структуры объектов
Отправлено: iyugov от 6 мая 2021, 23:35
Такой вариант ReDim - сначала экспоненциальное выделение памяти, потом линейное. В каких-то языках видел подобное - компромисс между частыми выделениями памяти и чрезмерным запасом. Да, лучше запросом получить количество сразу. Правда, если поставить сразу достаточный размер, то задержка всё равно сохранится.

Спасибо за наводки. Буду думать. Пробую несколько вариантов, в том числе с макросами на Python и, возможно, с вынесением части интерфейса в отдельный скрипт. LibreOffice в основном интересен как сервер отображения самих заданий, автоматической генерации и конвертации документов. В том, что не касается содержимого заданий, возможны варианты. К лету не жалко поэкспериментировать, но чем больше удачный выбор сэкономит времени в следующем учебном году, тем лучше.
Название: Re: Хранение и отображение иерархической (древовидной) структуры объектов
Отправлено: iyugov от 13 мая 2021, 14:56
Пока остановился всё-таки на отображении в форме, с помощью запроса с рекурсией. Надо идти дальше.
Название: Re: Хранение и отображение иерархической (древовидной) структуры объектов
Отправлено: economist от 13 мая 2021, 16:16
Выглядит вполне понятно, но все же не деревом.

Если же смотреть в сторону Python - контрол Treeview для tkinter выглядит лучше, поддерживает цвета, форматы, "зебру", под-деревья в другом окне.

В "LO-родном" Python - его вырезали, и через докачанный pip он не поставится. Но можно скопировать из установленного внешнего той же версии/разрядности: https://tk-tutorial.readthedocs.io/en/latest/tree/tree.html (у меня заработал даже из 3.8)
Название: Re: Хранение и отображение иерархической (древовидной) структуры объектов
Отправлено: iyugov от 13 мая 2021, 18:41
Тем оказалось уже 850, на 7 уровней вложенности. Оказалось, что такой список работает быстро, и подходящие темы в нём ищутся с меньшим числом телодвижений: вся иерархия уже раскрыта и видна, видны темы на соседних уровнях, вроде бы поддаётся фильтрации, можно вынести название из нижнего уровня вперёд и искать набором на клавиатуре. Вполне эффективный вариант получился. Кажется, он для моих целей удобнее, чем TreeView в принципе. А ещё он прямо на форме расположен, а на ней и без того есть над чем подумать, одной проблемой меньше.