2016-01-22 12 views
2

Из-за отсутствия какой-либо другой демонстрации Qt я использую демонстрацию SimpleTreeModel Qt widgets для реализации модели C++ для моего QML TreeView. Я определил роли, которые QML может использовать, но у меня возникают проблемы с их подключением к фактическим данным модели.Модель C++ для QML TreeView

Что я также нахожу интересным, так это то, что демонстрация виджета (C++) отлично работает, но TreeModel, похоже, не хранит данные в качестве своей переменной-члена .. мне кажется, что я царапаю голову. Я понял, что каждый TreeItem хранит все дочерние элементы, а TreeModel имеет только один rootItem, который, в свою очередь, хранит все данные в качестве своего дочернего элемента.

Класс TreeItem

class TreeItem 
{ 
public: 
    explicit TreeItem(const QList<QVariant> &data, TreeItem *parentItem = 0); 
    ~TreeItem(); 

    void appendChild(TreeItem *child); 

    TreeItem *child(int row); 
    int childCount() const; 
    int columnCount() const; 
    QVariant data(int column) const; 
    int row() const; 
    TreeItem *parentItem(); 

private: 
    QList<TreeItem*> m_childItems; 
    QList<QVariant> m_itemData; 
    TreeItem *m_parentItem; 
}; 

TreeModel класс

class TreeModel : public QAbstractItemModel 
{ 
    Q_OBJECT 

public: 
    enum DisplayRoles { 
     TitleRole = Qt::UserRole + 1, 
     SummaryRole 
    }; 

    explicit TreeModel(const QString &data, QObject *parent = 0); 
    ~TreeModel(); 

    QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; 
    Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE; 
    QVariant headerData(int section, Qt::Orientation orientation, 
         int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; 
    QModelIndex index(int row, int column, 
         const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; 
    QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE; 
    int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; 
    int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; 

    QHash<int, QByteArray> TreeModel::roleNames() const { 
     QHash<int, QByteArray> roles; 
     roles[TitleRole] = "title"; 
     roles[SummaryRole] = "summary"; 
     return roles; 
    } 


private: 
    void setupModelData(const QStringList &lines, TreeItem *parent); 

    TreeItem *rootItem; 
}; 

Модель загружает данные из default.txt

TreeModel::TreeModel(const QString &data, QObject *parent) 
    : QAbstractItemModel(parent) 
{ 
    QList<QVariant> rootData; 
    rootData << "Title" << "Summary"; 
    rootItem = new TreeItem(rootData); 
    setupModelData(data.split(QString("\n")), rootItem); 
} 

void TreeModel::setupModelData(const QStringList &lines, TreeItem *parent) 
{ 
    QList<TreeItem*> parents; 
    QList<int> indentations; 
    parents << parent; 
    indentations << 0; 

    int number = 0; 

    while (number < lines.count()) { 
     int position = 0; 
     while (position < lines[number].length()) { 
      if (lines[number].mid(position, 1) != " ") 
       break; 
      position++; 
     } 

     QString lineData = lines[number].mid(position).trimmed(); 

     if (!lineData.isEmpty()) { 
      // Read the column data from the rest of the line. 
      QStringList columnStrings = lineData.split("\t", QString::SkipEmptyParts); 
      QList<QVariant> columnData; 
      for (int column = 0; column < columnStrings.count(); ++column) 
       columnData << columnStrings[column]; 

      if (position > indentations.last()) { 
       // The last child of the current parent is now the new parent 
       // unless the current parent has no children. 

       if (parents.last()->childCount() > 0) { 
        parents << parents.last()->child(parents.last()->childCount()-1); 
        indentations << position; 
       } 
      } else { 
       while (position < indentations.last() && parents.count() > 0) { 
        parents.pop_back(); 
        indentations.pop_back(); 
       } 
      } 

      // Append a new item to the current parent's list of children. 
      parents.last()->appendChild(new TreeItem(columnData, parents.last())); 
     } 

     ++number; 
    } 
} 

Моя проблема заключается в этой функции, как я соедините роли с данными, которые хранятся в rootItem?. Примечание titleString и summaryString Возможные предлагаемые функции (при необходимости), но я не знаю, что писать в них, получить доступ к данным!

QVariant TreeModel::data(const QModelIndex &index, int role) const 
{ 
    if (!index.isValid()) 
     return QVariant(); 

    if (index.isValid() && role >= TitleRole) { 
     switch (role) { 
     case TitleRole: 
      return QVariant(titleString(rootItem(index))); // get title through rootItem? 
     case SummaryRole: 
      return QVariant(summaryString(rootItem(index))); // get summary through rootItem? 
     } 
    } 

    if (role != Qt::DisplayRole) 
     return QVariant(); 

    TreeItem *item = static_cast<TreeItem*>(index.internalPointer()); 

    return item->data(index.column()); 
} 

default.txt имеет следующие данные, но то же самое можно найти в самой Qt Creator демо, а также.

Getting Started    How to familiarize yourself with Qt Designer 
    Launching Designer   Running the Qt Designer application 
    The User Interface   How to interact with Qt Designer 

Designing a Component   Creating a GUI for your application 
    Creating a Dialog   How to create a dialog 
    Composing the Dialog  Putting widgets into the dialog example 
    Creating a Layout   Arranging widgets on a form 
    Signal and Slot Connections  Making widget communicate with each other 

Using a Component in Your Application Generating code from forms 
    The Direct Approach   Using a form without any adjustments 
    The Single Inheritance Approach Subclassing a form's base class 
    The Multiple Inheritance Approach Subclassing the form itself 
    Automatic Connections  Connecting widgets using a naming scheme 
     A Dialog Without Auto-Connect How to connect widgets without a naming scheme 
     A Dialog With Auto-Connect Using automatic connections 

Form Editing Mode   How to edit a form in Qt Designer 
    Managing Forms   Loading and saving forms 
    Editing a Form   Basic editing techniques 
    The Property Editor   Changing widget properties 
    The Object Inspector  Examining the hierarchy of objects on a form 
    Layouts    Objects that arrange widgets on a form 
     Applying and Breaking Layouts Managing widgets in layouts 
     Horizontal and Vertical Layouts Standard row and column layouts 
     The Grid Layout   Arranging widgets in a matrix 
    Previewing Forms   Checking that the design works 

Using Containers   How to group widgets together 
    General Features   Common container features 
    Frames    QFrame 
    Group Boxes    QGroupBox 
    Stacked Widgets   QStackedWidget 
    Tab Widgets    QTabWidget 
    Toolbox Widgets   QToolBox 

Connection Editing Mode   Connecting widgets together with signals and slots 
    Connecting Objects   Making connections in Qt Designer 
    Editing Connections   Changing existing connections 

Мой вывод показывает то же количество строк, что и в демонстрационных виджетах, за исключением того, что текста нет. Похоже, что он просто не связан с ролями должным образом, или роли не связаны с днем. Я прикрепляю снимок экрана моего вывода.

enter image description here

+0

filesystembrowser, по-видимому, лучше подходит - посмотрите на treeview на экране образцов QtCreator – CapelliC

+0

@CapelliC Это то, с чего я начал, функция 'data' работает со стандартным' QFileSystemModel' и только вызывает 'fileInfo (index)' to извлеките файл, о котором идет речь. Здесь модель данных - это пользовательские данные. На самом деле вопрос о том, как пройти эти данные. Мне нужна эта структура для работы, потому что мой фактический проект будет хранить данные таким же образом. – zar

+1

[Здесь] (https://github.com/bvanderlaan/ImaginativeThinking_tutorials/tree/master/Qt/QtQuick_TreeView) у вас есть хороший пример для начала. 'TreeItem' следует изменить, чтобы учесть ваши новые роли. – Tarod

ответ

3

Просто так, если кто-то пытается сделать то же самое, я понял это, и вот ответ. Метод данных модели должен читать следующее.

QVariant TreeModel::data(const QModelIndex &index, int role) const 
{ 
    if (!index.isValid()) 
     return QVariant(); 

    TreeItem *item = static_cast<TreeItem*>(index.internalPointer()); 

    if (index.isValid() && role >= TitleRole) { 
     switch (role) { 
     case TitleRole: 
      return item->data(0); 
     case SummaryRole: 
      return item->data(1); 
     } 
    } 

    if (role != Qt::DisplayRole) 
     return QVariant(); 

    return item->data(index.column()); 
} 

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

+1

Отлично, задан :) Спасибо, что поделились! Счастливое кодирование! – Tarod