将 QStandardItemModel 从 C++ 传递到 QtQuick / QML TableView 并显示它

Posted

技术标签:

【中文标题】将 QStandardItemModel 从 C++ 传递到 QtQuick / QML TableView 并显示它【英文标题】:Pass QStandardItemModel from C++ to QtQuick / QML TableView and display it 【发布时间】:2014-09-17 11:21:16 【问题描述】:

我目前正在尝试将 QStandardItemModel 传递给 QtQuick TableView 然后显示它。这基本上是我的代码(只是一个简化的摘录,所以我希望我没有在这里添加任何额外的错误)。

C++/Qt 部分:

foo.cpp

[...]

QStandardItemModel *Foo::getModel()

    QStandardItemModel *model = new QStandardItemModel(this);
    QList<QStandardItem*> standardItemList;

    QList<QString> data;
    data.append("Cat");
    data.append("Dog");
    data.append("Mouse");

    foreach (QString cell, comInputData->getHeadings()) 
        QStandardItem *item = new QStandardItem(cell);
        standardItemList.append(item);
    

    // we only add one row here for now; more will come later
    model->appendRow(standardItemList);
    standardItemList.clear();
    return model;


[...]

main.cpp

Foo f;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("myModel", f.getModel());
engine.load(QUrl(QStringLiteral("qrc:///InputView.qml")));

QtQuick / QML 部分:

InputView.qml

TableView 
    id: monitorInputVectorsTable
    [... positioning and sizing ...] 
    model: myModel

我想,我仍然缺少 QML 部分中的一些重要部分,是吗?我发现了一些这样的内联模型定义示例:

ListModel 
    id: libraryModel
    ListElement title: "A Masterpiece" ; author: "Gabriel" 
    ListElement title: "Brilliance"    ; author: "Jens" 

...以这种方式显示(在TableView-item中添加了以下内容):

TableViewColumn role: "title"  ; title: "Title" ; width: 100 
TableViewColumn role: "author" ; title: "Author" ; width: 200 

我的猜测:我也需要添加这样的一行。但是,我不知道从 C++ QStandardItemModel 那里获得角色?甚至有必要设置角色吗?至少带有“经典”QTreeView 的 QWidgets 示例只是设置了模型,一切都很好......

【问题讨论】:

对于 QStandardItemModel,您设置的数据的隐含角色是 Display 角色。我从未尝试在 TableView 上设置这样的模型,使用 ListView 更合适,因为您的模型中没有“列”概念。 感谢您的评论。在我的完整代码中,将有“列”,即参数(每个都有一个列)随时间变化(行)(这些值是从 csv 文件中解析的)。所以我认为 TableView 是正确的方法。虽然我现在添加了TableViewColumn role: "Display" ; title: "Title" ; ,但 TableView 仍然是空白的...:/ 好吧,我刚刚发现我应该尝试一个非大写的“显示”(``TableViewColumn role: "display" ; title: "Title" ; . Then the TreeView finally displays something: the first value (in the example "Cat") - which is logical because I have got only one row for now. Now I still need to display the other columns also. Adding just another TableViewColumn... ` 不起作用 - (因为它是同一个角色?)它只再次显示相同的第一个值。我想知道如何只显示一些列和/或如何手动设置角色? 如果你翻译一个 csv 来提供一个自定义模型,你应该继承 QAbstractTableModel。请参阅subclassing section。您需要在那里定义角色名称。 【参考方案1】:

您可以继承 QStandardItemModel 并重新实现 roleNames() 以定义您想要的角色名称:

#include <QStandardItemModel>

class MyModel : public QStandardItemModel


public:

    enum Role 
        role1=Qt::UserRole,
        role2,
        role3
    ;


    explicit MyModel(QObject * parent = 0): QStandardItemModel(parent)
    
    
    explicit MyModel( int rows, int columns, QObject * parent = 0 ): QStandardItemModel(rows, columns, parent)
    
    

    QHash<int, QByteArray> roleNames() const
    
         QHash<int, QByteArray> roles;
         roles[role1] = "one";
         roles[role2] = "two";
         roles[role3] = "three";

         return roles;
    
;

添加项目后,您可以为模型设置数据,例如:

model->setData(model->index(0,0), "Data 1", MyModel::role1);
model->setData(model->index(0,1), "Data 2", MyModel::role2);
model->setData(model->index(0,2), "Data 3", MyModel::role3);

现在在 qml 中,您可以通过角色名称访问不同的列:

TableView 

    TableViewColumn title: "1"; role: "one"; width: 70 
    TableViewColumn title: "2"; role: "two"; width: 70   
    TableViewColumn title: "3"; role: "three"; width: 70 

    model: myModel


【讨论】:

哇,谢谢,这正是我想要的(现在可以使用了)!很难找到实现roleNames()-方法所需的文档,甚至更难找到有关如何实现该方法的示例......只有一个问题:在我现在找到的其他示例中(在知道这个函数名称之后),他们使用Qt::UserRole + 1 而不仅仅是Qt::UserRole。哪一个是对的,为什么? 我认为没有区别。在文档中,您可以看到 Qt::UserRole 是自定义角色的第一个值。因此,您可以将其用作第一个或从大于Qt::UserRole 的任意值开始。 我最初也是这么想的。但后来我看到了所有其他使用 +1 的例子......无论如何,谢谢你的回答! 我也面临同样的问题,我在课堂上定义了角色名称,但在 TableView 中仍然没有得到任何东西。我应该在哪里定义 setData() 映射?我在附加数据后设置它。【参考方案2】:

在我的情况下(Qt 5.5),像 Nejats 回答中那样向模型添加数据不起作用。必须按如下方式添加数据:

QStandardItem* it = new QStandardItem();
it->setData("data 1", MyModel::role1);
it->setData("data 2", MyModel::role2);
it->setData("data 3", MyModel::role3);
model->appendRow(it);

下面是带有此修改的 Nejat 答案的完整示例(也可在此处获得:https://github.com/psimona/so-qt-QStandardItemModel-Example)

main.cpp

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QtQml>

// QStandardItemModel derived class
#include <QStandardItemModel>
class MyModel : public QStandardItemModel 

public:
    enum Role 
        role1=Qt::UserRole,
        role2,
        role3
    ;

    explicit MyModel(QObject * parent = 0): QStandardItemModel(parent)
    explicit MyModel( int rows, int columns, QObject * parent = 0 )
        : QStandardItemModel(rows, columns, parent)

    QHash<int, QByteArray> roleNames() const
         QHash<int, QByteArray> roles;
         roles[role1] = "one";
         roles[role2] = "two";
         roles[role3] = "three";
         return roles;
    
;


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

    QApplication app(argc, argv);


    MyModel* model = new MyModel;


    QStandardItem* it = new QStandardItem();
    it->setData("data 1", MyModel::role1);
    it->setData("data 2", MyModel::role2);
    it->setData("data 3", MyModel::role3);
    model->appendRow(it);

    it = new QStandardItem();
    it->setData("more data 1", MyModel::role1);
    it->setData("more data 2", MyModel::role2);
    it->setData("more data 3", MyModel::role3);
    model->appendRow(it);

    QQmlApplicationEngine engine;
    // register cpp model with QML engine
    engine.rootContext()->setContextProperty("myModel", model);

    // Load qml file in QML engine
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();

main.qml

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2

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

    TableView 

        anchors.fill: parent

        TableViewColumn title: "1"; role: "one"; width: 150 
        TableViewColumn title: "2"; role: "two"; width: 150   
        TableViewColumn title: "3"; role: "three"; width: 150 

        model: myModel

    

【讨论】:

以上是关于将 QStandardItemModel 从 C++ 传递到 QtQuick / QML TableView 并显示它的主要内容,如果未能解决你的问题,请参考以下文章

如何从函数传递 QStandardItemModel?

qt - 如何对 qstandarditemmodel 进行永久排序

拖放到 QTreeView 中的 QStandardItemModel 不起作用

如何使用qstandarditemmodel获取qtableview中的数据

如何从 QML 访问嵌套的 QStandardItemModel 的项目?

有没有办法将 QTableView 模型转换为 QStandardItemModel