为 QML TreeView 创建模型

Posted

技术标签:

【中文标题】为 QML TreeView 创建模型【英文标题】:Create Model for QML TreeView 【发布时间】:2017-07-18 12:08:09 【问题描述】:

我正在尝试使用 QML TreeView 模型。 Qt 中的示例不包括如何创建模型。我阅读了这个post 并尝试使用来自@Tarod 的代码,但结果不是我所期望的。

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "animalmodel.h"
#include <qqmlcontext.h>
#include <qqml.h>

int main(int argc, char *argv[])

    QGuiApplication app(argc, argv);

    AnimalModel model;
    model.addAnimal("wolf", "Medium");
    model.addAnimal("Bear", "Large");

    QQmlApplicationEngine engine;
    QQmlContext *ctxt = engine.rootContext();
    ctxt->setContextProperty("myModel", &model);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();

动物模型.h

#ifndef ANIMALMODEL_H
#define ANIMALMODEL_H

#include <QStandardItemModel>


class AnimalModel : public QStandardItemModel

    Q_OBJECT //The Q_OBJECT macro must appear in the private section of a class definition that declares its own signals and slots or that uses other services provided by Qt's meta-object system.
public:
    enum AnimalRoles 
        TypeRole = Qt::UserRole + 1,
        SizeRole
    ;

    AnimalModel(QObject *parent = 0);

    Q_INVOKABLE void addAnimal(const QString &type, const QString &size);

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;

protected:
    QHash<int, QByteArray> roleNames() const;
;

#endif // ANIMALMODEL_H

动物模型.cpp

#include "animalmodel.h"

AnimalModel::AnimalModel(QObject *parent)
    : QStandardItemModel(parent)




void AnimalModel::addAnimal(const QString &type, const QString &size)

    QStandardItem* entry = new QStandardItem();
    entry->setData(type, TypeRole);

    auto childEntry = new QStandardItem();
    childEntry->setData(size, SizeRole);
    entry->appendRow(childEntry);

    appendRow(entry);


QVariant AnimalModel::data(const QModelIndex & index, int role) const 
    QStandardItem *myItem = itemFromIndex(index);

    if (role == TypeRole)
        return myItem->data(TypeRole);
    else if (role == SizeRole) 
        if (myItem->child(0) != 0)
        
            return myItem->child(0)->data(SizeRole);
        
    
    return QVariant();


QHash<int, QByteArray> AnimalModel::roleNames() const 
    QHash<int, QByteArray> roles;
    roles[TypeRole] = "type";
    roles[SizeRole] = "size";
    return roles;

main.qml

import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 1.4


ApplicationWindow 
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    menuBar: MenuBar 
        Menu 
            title: qsTr("&File")
            MenuItem 
                text: qsTr("&Open")
                onTriggered: messageDialog.show(qsTr("Open Action Triggered"));
            
            MenuItem 
                text: qsTr("&Exit")
                onTriggered: Qt.quit();
            
        
    


    TreeView 
        anchors.fill: parent
        model: myModel
        TableViewColumn 
            title: "Name"
            role: "type"
            width: 300
        
        TableViewColumn 
            title: "Size"
            role: "size"
            width: 300
        
    

我得到的是这样的: Result

我想要的是作为动物类型的孩子的动物大小。

【问题讨论】:

【参考方案1】:

模型子类化是 Qt 中最严重的雷区之一。建议始终让它通过模型测试 (https://wiki.qt.io/Model_Test) 以查看一切是否正确实施。

另一方面,在 90% 的情况下,您根本不需要对模型进行子类化,因为 Qt 提供的默认模型工作得很好。我要做的就是使用 QStandardItemModel,在 C++ 端,只使用 QAbstractItemModel 接口(即强迫自己使用QAbstractItemModel* model = new QStandardItemModel(/*parent*/);),如果将来你觉得你真的需要重新实现模型(为了提高效率) 您只需要更改现有代码中的 1 行。

在你的情况下:

void AnimalModel::addAnimal(const QString &type, const QString &size)

    if(columnCount()==0) insertColumn(0); // make sure there is at least 1 column
    insertRow(rowCount()); // add a row to the root
    const QModelIndex addedIdx = index(rowCount()-1,0);
    setData(addedIdx, type, TypeRole); // set the root data
    insertRow(rowCount(addedIdx),addedIdx ); // add 1 row ...
    insertColumn(0,addedIdx ); // ... and 1 column to the added root row
    setData(index(0,0,addedIdx), size, SizeRole); // set the data to the child


【讨论】:

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

QML 创建 TreeView 动态模型的正确方法是啥?

QML TreeView 的 C++ 模型

将数据添加到 QML TreeView

来自模型的 QML 树视图

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

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