Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/9: Рейтинг темы: голосов - 9, средняя оценка - 4.67
0 / 0 / 0
Регистрация: 08.08.2015
Сообщений: 91

Не могу отладить древовидную моделью в Qt

04.10.2015, 16:34. Показов 1833. Ответов 17
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Прошу помощи по созданию древовидной модели. Элементы не отображаются. Ранее делал все работало...

В модель передается список элементов.
Каждый элемент имеет указатель на родителя и список потомков (все это определяется конструктором);
Естественно переопределены все методы требующие для построения простого дерева(данные, кол. столбцов, кол. рядов, индек и родитель)

Сама модель сделана по примеру Simple Tree Model. Должен ли rootItem быть включеным в этот список?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
04.10.2015, 16:34
Ответы с готовыми решениями:

не могу отладить программу в Eclipce
Пишет Cannot find a free socket for the debugger Java Runtime Environment (JRE) и Java Development Kit - JDK стоят... Помогите...

Борьба с потоками, не могу отладить
Потенциально проблемный кусок кода вызов слота updateModel(): class HistoryTradeDealView : public QDockWidget { Q_OBJECT ...

не могу отладить игру (Pascal)
вот текст игры program sheapkiller; uses crt,graph; type point = record x1,y1,f,g:integer; end; const d=10000; label 1; var ...

17
205 / 165 / 41
Регистрация: 25.10.2013
Сообщений: 527
04.10.2015, 18:33
Без кода не понятно. Что за RootItem?
0
0 / 0 / 0
Регистрация: 08.08.2015
Сообщений: 91
04.10.2015, 20:25  [ТС]
Если открыть пример Qt стандартный Simple Tree Model, то в нем в классе самой модели есть Item *rootItem он как бы отделен от данных. Указатель на первый элемент. Я не совсем понимаю, взяимодействует ли он с самими данными? Предполагаю, что у меня данные должны содержать этот rootItem и соответствующие указатили друг на друга: потомки и родителя.
0
44 / 44 / 12
Регистрация: 05.04.2015
Сообщений: 345
04.10.2015, 21:06
Нужен все таки код. Может просто не происходит заполнение данными. И да rootItem - это корневой элемент. Просто в функции data и parent сделано так что он не отображается. Но он есть в функции headerData.
0
0 / 0 / 0
Регистрация: 08.08.2015
Сообщений: 91
04.10.2015, 21:47  [ТС]
Т.е. в самой структуре - QList<Мои элементы> должен быть этот корневой элемент с соответствующими ссылками друг на друга?
Корневой элемент(rootItem)
(содержит список дочек)
|
|___Дочерний элемент 1 (содержит указатель на корневой элемент)

Код громоздкий, надо в целом смотреть...пока пробую сам ковыряться. Там элементы создаваемые являются потомками "фабричного метода".

Попытаюсь объяснить:
В модель передаются данные в виде списка QList<INodeProduct *>

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void NodeOwnerModel::setDataSource(const QList<INodeProduct *> &dataSource)
{
  dataSource_ = dataSource; // Это новые данные dataSource_
                                          // в этих данных уже есть элементы хранящие указатель на родителя
                                          // и несколько элементов родитель которых = 0
 
// А теперь добавляем в список магический корневой элемент
  for (auto i : dataSource_)
  {
    if(!i->getParent())
    {
      i->setParent(rootItem_); // соответственно все элементы у которых нет родителя "усыновляются" rootItem
      rootItem_->appendChild(i); // и сам корневой элемент хранит своих потомков
    }
  }
// Теперь модель дерева полная, и включает rootItem
  dataSource_.append(rootItem_); // добавляем его в спиок - список готов
  beginResetModel(); // ну и обновились
  endResetModel();
}
Пять методов с конструктором где корень создается:

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
NodeOwnerModel::NodeOwnerModel(QObject *parent) :
  QAbstractItemModel(parent)
{
  rootItem_ = new INodeProduct;
}
 
QModelIndex NodeOwnerModel::index(int row, int column, const QModelIndex &parent) const
{
  if (!hasIndex(row, column, parent))
    return QModelIndex();
 
  INodeProduct *parentItem;
 
  if (!parent.isValid())
    parentItem = rootItem_;
  else
    parentItem = static_cast<INodeProduct *>(parent.internalPointer());
 
  INodeProduct *childItem = parentItem->getChildren().at(row);
  if (childItem)
    return createIndex(row, column, childItem);
  else
    return QModelIndex();
}
 
QModelIndex NodeOwnerModel::parent(const QModelIndex &index) const
{
  if (!index.isValid())
    return QModelIndex();
  INodeProduct *childItem = static_cast<INodeProduct *>(index.internalPointer());
  INodeProduct *parentItem = childItem->getParent();
  if (parentItem == rootItem_)
    return QModelIndex();
  return createIndex(parentItem->row(), 0, parentItem);
}
 
int NodeOwnerModel::rowCount(const QModelIndex &parent) const
{
  INodeProduct *parentItem;
 
  if (!parent.isValid())
    parentItem = rootItem_;
  else
    parentItem = static_cast<INodeProduct *>(parent.internalPointer());
 
  return parentItem->getChildren().count();
}
 
int NodeOwnerModel::columnCount(const QModelIndex &parent) const
{
  return parent.isValid() ? 1 : 0;
}
 
QVariant NodeOwnerModel::data(const QModelIndex &index, int role) const
{
  if (!index.isValid())
    return QVariant();
  if (role != Qt::DisplayRole)
    return QVariant();
  INodeProduct *product = static_cast<INodeProduct *>(index.internalPointer());
  return product->getName();
}
Это сам элемент, кастрированый оставил только то что относится к модели:

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class INodeProduct : public QObject
{
    Q_OBJECT
 
    int row() const;
    inline INodeProduct *getParent() const { return parent_; }
    inline void setParent(INodeProduct *parent) { parent_ = parent; }
    inline QList<INodeProduct *> getChildren() const { return children_; }
    inline void setChildren(const QList<INodeProduct *> &children) { children_ = children; }
    inline void appendChild(INodeProduct *child) { children_.append(child); }
 
  protected:
 
// частичка данных
    QString creatorId_;
    QString name_;
 
    INodeProduct *parent_;
    QList<INodeProduct *> children_;
}
И еще кусок важного сам конструктор и метод row() как уж их создаю в клиенте кидать не буду:

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
INodeProduct::INodeProduct(INodeProduct *parentItem, QObject *parent) :
  QObject(parent),
  parent_(parentItem)
{
  if(parent_)
    parent_->appendChild(this);
}
 
INodeProduct::~INodeProduct()
{
  qDeleteAll(children_);
}
 
int INodeProduct::row() const
{
  if (parent_)
    return parent_->getChildren().indexOf(const_cast<INodeProduct *>(this));
  return 0;
}
Буду крайне признателен, кто ткнет носом где не так!
0
205 / 165 / 41
Регистрация: 25.10.2013
Сообщений: 527
05.10.2015, 07:32
Цитата Сообщение от kavashige Посмотреть сообщение
C++ (Qt)
1
dataSource_.append(rootItem_); // добавляем его в спиок - список готов
Зачем? Это же элемент-пустышка, который просто служит root-элементом. Он нигде не отображается. В моделях вообще можно обойтись без него.
Цитата Сообщение от kavashige Посмотреть сообщение
Буду крайне признателен, кто ткнет носом где не так!
У вас ColumnCount - 0. Документацию-то всё-таки читайте. QAbstractItemModel::columnCount returns the number of columns for the children of the given parent.
0
0 / 0 / 0
Регистрация: 08.08.2015
Сообщений: 91
05.10.2015, 08:53  [ТС]
Shtirliz72, я про rootItem и спрашивал, нужен ли он в списке данных? Первоначальная версия передачи данных была такая:

C++ (Qt)
1
2
3
4
5
6
void NodeOwnerModel::setDataSource(const QList<INodeProduct *> &dataSource)
{
  dataSource_ = dataSource;
  beginResetModel();
  endResetModel();
}
но после того как не взлетело и и решил что корень нужно включить в datasource_;

У вас ColumnCount - 0. Документацию-то всё-таки читайте. QAbstractItemModel::columnCount returns the number of columns for the children of the given parent.
Не верю т.к. return parent.isValid() ? 1 : 0; Если индекс родителя true вернет 1
0
205 / 165 / 41
Регистрация: 25.10.2013
Сообщений: 527
05.10.2015, 09:12
Лучший ответ Сообщение было отмечено kavashige как решение

Решение

Цитата Сообщение от kavashige Посмотреть сообщение
Не верю т.к. return parent.isValid() ? 1 : 0; Если индекс родителя true вернет 1
А мы тут в верю\не верю играем?
К вам вопрос на засыпку, а какой же индекс у root'a? Правильно, QModelIndex(). Невалидный. Поэтому у вас не отображаются столбцы для всех детей рутового индекса.

Пишите там
C++ (Qt)
1
2
3
4
int NodeOwnerModel::columnCount(const QModelIndex &parent) const
{
  return 1;
}
и смотрите, заработает ли.
1
0 / 0 / 0
Регистрация: 08.08.2015
Сообщений: 91
05.10.2015, 12:25  [ТС]
Беллисимо! Вот я дурак, действительно 0 был, а я уверен, что был единица. Все работает!

Добавлено через 3 часа 5 минут
И все же по поводу rootItem, сам rootItem не отображается но...

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void NodeOwnerModel::setDataSource(const QList<INodeProduct *> &dataSource)
{
  dataSource_ = dataSource;
// если убрать начиная отсюда...
  for (auto i : dataSource_)
  {
    if(!i->getParent())
    {
      i->setParent(rootItem_);
      rootItem_->appendChild(i);
    }
  }
  dataSource_.append(rootItem_); // если этого нет, то дерево также не отображается
// до этого места
  beginResetModel();
  endResetModel();
}
0
205 / 165 / 41
Регистрация: 25.10.2013
Сообщений: 527
05.10.2015, 12:43
Цитата Сообщение от kavashige Посмотреть сообщение
И все же по поводу rootItem, сам rootItem не отображается но...
Тут я без понятия. Ты слишком мало кода предоставил, чтобы я мог судить, как там у тебя model работает.
0
0 / 0 / 0
Регистрация: 08.08.2015
Сообщений: 91
05.10.2015, 13:36  [ТС]
Все что есть, вся модель целиком выше, я еще коментарии в коде добавил, мб ты их не прочитал (// если убрать начиная отсюда...и.т.д.), 5ть методов и метод setDataSource
0
205 / 165 / 41
Регистрация: 25.10.2013
Сообщений: 527
05.10.2015, 14:06
Цитата Сообщение от kavashige Посмотреть сообщение
Все что есть, вся модель целиком выше, я еще коментарии в коде добавил, мб ты их не прочитал (// если убрать начиная отсюда...и.т.д.), 5ть методов и метод setDataSource
Правда? Я как-то в упор не вижу объявление класса NodeOwnerModel

Добавлено через 4 минуты
И я как-то не понимаю один момент: зачем ты вообще используешь в древовидной модели список?
0
44 / 44 / 12
Регистрация: 05.04.2015
Сообщений: 345
05.10.2015, 14:39
В примере Qt, я делал для себя дерево тоже по нему, rootItem используется для того чтобы было удобно очищать память (он корневой элемент) и для хранения данных горизонтального хэдера. Покажи headerData. Хоть у меня дерево тоже из примеров, мне немного тяжело ориентироваться потому что имена переменных изменены.
0
0 / 0 / 0
Регистрация: 08.08.2015
Сообщений: 91
05.10.2015, 21:41  [ТС]
Вот заголовочник, но там ничего нового:

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifndef NODEOWNERMODEL_H
#define NODEOWNERMODEL_H
 
#include <QObject>
#include <QAbstractItemModel>
 
namespace node_module {
class NodeOwnerModel;
}
 
QT_BEGIN_NAMESPACE
class INodeProduct;
QT_END_NAMESPACE
 
class NodeOwnerModel : public QAbstractItemModel
{
    Q_OBJECT
 
  public:
    explicit NodeOwnerModel(QObject *parent = 0);
    ~NodeOwnerModel();
 
    QModelIndex index(int row,
                      int column,const QModelIndex &parent = QModelIndex()) const override final;
    QModelIndex parent(const QModelIndex &index) const override final;
    int rowCount(const QModelIndex &parent = QModelIndex()) const override final;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override final;
    QVariant data(const QModelIndex &index, int role) const override final;
    Qt::ItemFlags flags(const QModelIndex &index) const override final;
    QVariant headerData(int section, Qt::Orientation orientation,
                        int role = Qt::DisplayRole) const override final;
 
    inline QList<INodeProduct *> dataSource() const { return dataSource_; }
    void setDataSource(const QList<INodeProduct *> &dataSource);
 
  private:
    QList<INodeProduct *> dataSource_;
    INodeProduct *rootItem_;
};
 
#endif // NODEOWNERMODEL_H
По поводу списка, вопросом оптимизации пока не касался, какой первый контейнер в голову пришел, такой и был использован. В данном случае можно смело заменить на QVector. А в чем вы предложите хранить? Сразу уточню цель: будет перетаскивание элементов, вставки внутрь.
0
205 / 165 / 41
Регистрация: 25.10.2013
Сообщений: 527
05.10.2015, 22:48
Цитата Сообщение от kavashige Посмотреть сообщение
Вот заголовочник, но там ничего нового:
На самом деле - важнейшая информация. Его надо было приводить в первую очередь. Там вся структура вашего класса.

Цитата Сообщение от kavashige Посмотреть сообщение
По поводу списка, вопросом оптимизации пока не касался, какой первый контейнер в голову пришел, такой и был использован. В данном случае можно смело заменить на QVector. А в чем вы предложите хранить? Сразу уточню цель: будет перетаскивание элементов, вставки внутрь.
Древовидная структура - она намного сложнее в реализации, нежели списочная. Если вам потом не нужно будет вставлять дочерние элементы в другие элементы списка - тогда древовидная структура и не нужна. Как не нужен и QTreeView.

Если хотите совета - более подробно опишите, что вы хотите и как оно у вас будет действовать. Чем более полно опишите - тем точнее будет совет.
0
0 / 0 / 0
Регистрация: 08.08.2015
Сообщений: 91
06.10.2015, 08:52  [ТС]
По своей структуре это напоминает OPC сервер.
Список узлов. Каждый узел хранит у себя дочерний узел и список параметров. Список параметров будет формировать таблицу.
Таким образом слева у нас дерево узлов (древовидная модель), справа таблица с параметрами (списковая модель). А модель данных получается "список - списков".
Должны быть реализованы следующие возможности:
Редактирование узла.
Удаление узла.
Вставка нового узла в любой родительский узел.
Копирование узла и создание новой копии узла принадлежащей другому родителю.
Редактирование параметров. Добавление новых параметров, удаление.
Перетаскивание узлов.

Количество узлов не более 200 шт. Количество параметров для каждого узла не более 1000шт. (С большим запасом)
Структура списка хранится в БД. При старте, приложение считывает из БД значения и формирует список, который уже используется.

Реализация сейчас такая:
Есть класс NodeOwner он и хранит весь список и взаимодействует с БД, класс является одиночкой. При изменении любого параметра срабатывает сигнал dataChanged(), и модель полностью заменяет данные(тут конечно очень не оптимально, т.к. каждый раз модель заново получает целый список, но подобная реализация уже была и каких то проблем с быстродействием не наблюдалось список с 10000 параметров мгновенно обновлялся)
0
205 / 165 / 41
Регистрация: 25.10.2013
Сообщений: 527
06.10.2015, 11:52
Цитата Сообщение от kavashige Посмотреть сообщение
По своей структуре это напоминает OPC сервер.
Список узлов. Каждый узел хранит у себя дочерний узел и список параметров. Список параметров будет формировать таблицу.
Таким образом слева у нас дерево узлов (древовидная модель), справа таблица с параметрами (списковая модель). А модель данных получается "список - списков".
Должны быть реализованы следующие возможности:
Редактирование узла.
Удаление узла.
Вставка нового узла в любой родительский узел.
Копирование узла и создание новой копии узла принадлежащей другому родителю.
Редактирование параметров. Добавление новых параметров, удаление.
Перетаскивание узлов.
Количество узлов не более 200 шт. Количество параметров для каждого узла не более 1000шт. (С большим запасом)
Структура списка хранится в БД. При старте, приложение считывает из БД значения и формирует список, который уже используется.
Реализация сейчас такая:
Есть класс NodeOwner он и хранит весь список и взаимодействует с БД, класс является одиночкой. При изменении любого параметра срабатывает сигнал dataChanged(), и модель полностью заменяет данные(тут конечно очень не оптимально, т.к. каждый раз модель заново получает целый список, но подобная реализация уже была и каких то проблем с быстродействием не наблюдалось список с 10000 параметров мгновенно обновлялся)
Ясно. Тут уж вам решать как это должно быть представленно в наилучшем для чтения виде.
Насчёт модели: если же крайне просто делать, то это обычное дерево. Списки параметров можно не использовать. Просто каждый параметр - это узел дерева, не имеющий потомков и ссылающийся на данные типа параметр. А каждый узел из списка узлов - это узел дерева, который может иметь или не иметь потомков и ссылающийся на данные типа узел. В данном случае ваша модель будет максимально похожа на обычную файловую модель, где есть папки(узлы) и файлы(параметры). Примеров подобной модели в интернете - масса. Вполне возможно что данная модель ни разу не является оптимальной, но она крайне проста. Про оптимизации и прочее - виднее явно вам. Только вы знаете и полностью владеете информацией о том, как данная модель будет использоваться и какие данные как часто она будет представлять. Так что могу пожелать только удачи.
1
0 / 0 / 0
Регистрация: 08.08.2015
Сообщений: 91
08.10.2015, 07:30  [ТС]
Shtirliz72, спасибо вам. Я в творческом процессе...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.10.2015, 07:30
Помогаю со студенческими работами здесь

Нужно отладить, не могу понять, на что он ругается!
Вот собственно задание, и решение к нему, не могу понять почему он ругается, и кривовато работает!

Компилятор оптимизировал мой код, и я не могу его отладить
пишу лабу одногруппнице. задание: определить двунаправленный циклический список. элементы типа char* реализовать функции: 1. проверка...

Не могу отладить программу, не понимаю, что нужно сделать
Здравствуйте, срочно нужна помощь в дописании программы! Необходимо, чтобы программа запоминала введенный массив в пункте 1 меню, и...

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

Организовать древовидную структуру данных
ПОМОГИТЕ. Организовать древовидную структуру данных в БД: хранение и их модификацию (у меня детали входят в сборку), чтобы было можно...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru