QML TreeView 的 C++ 模型

Posted

技术标签:

【中文标题】QML TreeView 的 C++ 模型【英文标题】:C++ model for QML TreeView 【发布时间】:2016-01-22 22:09:51 【问题描述】:

由于缺少任何其他 Qt 演示,我正在使用 Qt 小部件的 SimpleTreeModeldemo 为我的 QML TreeView 实现 C++ 模型。我已经定义了角色,因此 QML 可以使用它,但我无法将它们与实际模型数据连接起来。

我还发现有趣的是小部件 (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 中的数据联系起来?。注意 titleStringsummaryString 是可能的建议函数(如果需要),但我不知道在其中写什么才能访问数据!

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

我的输出显示的行数与小部件演示中的行数相同,只是没有文本。似乎它只是没有正确连接到角色或角色没有连接到一天。我附上我的输出的屏幕截图。

【问题讨论】:

filesystembrowser 似乎更适合 - 在 QtCreator 示例屏幕中查找树视图 @CapelliC 这就是我开始使用的,那里的data 函数与标准QFileSystemModel 一起使用,并且只调用fileInfo(index) 来检索有问题的文件。这里的数据模型是自定义数据。如何遍历这些数据确实是一个问题。我需要这种结构才能工作,因为我的实际项目将以相同的方式存储数据。 Here 你有一个很好的例子。应修改 TreeItem 以考虑您的新角色。 【参考方案1】:

因此,如果有人尝试做同样的事情,我想通了,这就是答案。模型的数据方法应如下所示。

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 可以在实际应用程序中更改以存储特定数据,在这种情况下,上述方法将指向该数据而不是列号方法。

【讨论】:

太好了,扎达内 :) 谢谢分享!编码愉快!

以上是关于QML TreeView 的 C++ 模型的主要内容,如果未能解决你的问题,请参考以下文章

QML TreeView按级别或自定义委托显示节点

为 QML TreeView 创建模型

这是 QML 中最小可行的 TreeView 模型吗?

QML TreeView 是不是支持模型发出的信号 layoutChanged?

将数据添加到 QML TreeView

来自模型的 QML 树视图