使用C++类为GridView设置Qt/QML属性

4

首先,我创建了一个新的C++类,其中包含一个成员函数,该函数返回一个字符串:

#ifndef TESTNAME_H
#define TESTNAME_H

#include <QObject>
#include <QString>
#include <QVariant>


class testname : public QObject
{

    Q_OBJECT;

public:
    testname();
    Q_INVOKABLE QString getName();
};

#endif // TESTNAME_H


#include "testname.h"

testname::testname()
{
}


QString testname::getName() {

    return "sometext";
}

我有一个 QML 文件,中间只有一段文本,像这样:

import QtQuick 1.1

Rectangle {
    width: 360
    height: 360

    Text {
        id: text1
        anchors.centerIn: parent
        text: testqml
        font.pixelSize: 12
    }
}

请注意,属性“text”是名为“testqml”的变量。此变量包含上述类的函数返回的字符串。此代码位于main.cpp中:
#include <QApplication>
#include "qmlapplicationviewer.h"
#include <testname.h>
#include <QDeclarativeContext>
#include <QDebug>

Q_DECL_EXPORT int main(int argc, char *argv[])
{
    QScopedPointer<QApplication> app(createApplication(argc, argv));


    // Create instance of "testname"
    testname *test = new testname;

    QmlApplicationViewer viewer;

    viewer.rootContext()->setContextProperty("testqml", test->getName());

    viewer.addImportPath(QLatin1String("modules"));
    viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
    viewer.setMainQmlFile(QLatin1String("qml/classtest/main.qml"));
    viewer.showExpanded();

    return app->exec();
}

使用setContextProperty函数,返回的字符串将暴露给qml文件,并在运行程序中正确显示。但我实际上想继承一个用于GridView的模型。因此,我在QML中创建了一个带有一个列表元素的GridView:
import QtQuick 1.1

Rectangle {
    width: 360
    height: 360

    GridView {
        id: grid_view1
        anchors.centerIn: parent
        width: 140
        height: 140
        cellHeight: 70
        delegate: Item {
            x: 5
            height: 50
            Column {
                spacing: 5
                Rectangle {
                    width: 40
                    height: 40
                    color: colorCode
                    anchors.horizontalCenter: parent.horizontalCenter
                }

                Text {
                    x: 5
                    text: name
                    anchors.horizontalCenter: parent.horizontalCenter
                    font.bold: true
                }
            }
        }
        model: ListModel {

            ListElement {
                name: testqml
                colorCode: "grey"
            }


        }
        cellWidth: 70
    }
}

变量“testqml”现在在列表的“name”字段中,该字段是一个字符串。如果我使用一个像“likethis”这样的字符串,它会正确显示。但是,如果我运行我的程序(main.cpp和class保持不变),我会得到以下错误:
ListElement: cannot use script for property value 
                     name: testqml 
                     ^ 

我现在遇到了困难。我找到了一个类似的问题#QTBUG-16289并报告了错误,但我不知道如何解决我的问题。有什么想法、教程或其他东西可以帮助我解决问题吗?

谢谢和问候 :)


你成功了吗? - Bruce Dean
嗨 :) 谢谢你的非常非常棒的回答!我正在努力工作,但输入量真的很大 :) 你的代码有效(谢谢!!),你的猜测是正确的:我想继承其中一个模型类,特别是QFileSystemModel。我目前还不完全理解这些角色。有两个角色实现了,但只有一行“Qt :: UserRole +1”..目前我正在尝试将你的代码转移到文件系统模型中。如果我卡住了,也许我可以向你寻求帮助 :) 再次感谢你非常详细的回答! :) - owlet
1个回答

4
我运行了您的代码并重现了您的错误,但是您最终想要做什么呢?
您的委托表明您想从C++注入多个带有“名称”和“颜色”的模型项,否则,为什么使用GridView,对吗?
如果不是这种情况,那么后面的内容可能不太有用,或者它的某个变体可能会有用。因此,我定义了一个示例,以说明您可能正在尝试完成的操作。
总之,在我的系统上,在创建任意数量的模型项(在本例中为20)之后,可滚动的GridView委托(在滚动范围的中间位置)如下所示: enter image description here 正如我所说,似乎您想将一些QString项从C++模型注入到QML GridView中,注意使用GridView意味着您想要多个项。在大多数情况下,您将希望继承预定义的Qt Model,它会自动处理几个重要细节,例如使QML视图与模型保持同步,并在删除项目或添加新项目时自动更新视图。
考虑到这一点,QAbstractListModel是一个方便的类,可以基于该类构建您的模型(这不是唯一的选项,请参见帮助文件)。乍一看,设置此模型可能会显得复杂,因此我定义了一个最小版本,希望它能说明您想要做什么。
以下是模型的代码(注意:我将所有代码放在.h文件中,因此不需要.m文件)。我还创建了一些“项”以注入到模型中,为简单起见,使用struct Item,如下所定义,但这些可以很容易地成为另一个适当定义的类的实例:
#include <QString>
#include <QColor>
#include <QDebug>
#include <QAbstractListModel>

// Create an Item so we have something to put in the model:
struct Item {
    QString name;
    QString color;
};

class testname : public QAbstractListModel
{
    Q_OBJECT

public:
    explicit testname(QObject *parent = 0) : QAbstractListModel(parent)
    {
        // Create some items and then add to the model:
        int N = 20;
        QStringList colorNames = QColor::colorNames();
        Item* items = new Item[N];
        for (int i = 0; i < N; i++) {
            items[i].name = QString("item"+QString::number(i));
            items[i].color = colorNames[i];
            //qDebug() << items[i].name << "; " << items[i].color;
            _model<<items[i];
        }
    }

    // enum DataRoles for QAbstractListModel:
    enum DataRoles {
        NameRole = Qt::UserRole + 1,
        ColorRole
    };

    // addData() method for QAbstractListModel:
    void addData(const Item& entry) {
        beginInsertRows(QModelIndex(), rowCount(), rowCount());
        _model << entry;
        endInsertRows();
    }

    // rowCount() method for QAbstractListModel:
    int rowCount(const QModelIndex & parent = QModelIndex()) const {
        return _model.count();
    }

    // data() required for QAbstractListModel:
    QVariant data(const QModelIndex & index, int role) const {
        if ( !index.isValid() || index.row() < 0 || index.row() >= _model.count() )
            return QVariant();
        Item modelEntry = _model[index.row()];
        if (role == NameRole) {return modelEntry.name;}
        if (role == ColorRole) {return modelEntry.color;}
        return QVariant();
    }

    // roleNames() method for QAbstractListModel:
    QHash<int,QByteArray> roleNames() const {
        QHash<int, QByteArray> roles;
        roles[NameRole] = "Name";
        roles[ColorRole] = "Color";
        return roles;
    }

private:
    // Below are the model items:
    QList<Item> _model;

};

以下是使用上文在main.cpp中定义并注册为“testqml”的C++模型的QML代码,并通过属性model:GridView中定义。
请注意,在委托(delegate)中,模型的颜色和名称属性在上述类中定义为角色名称(这些名称可以是您喜欢的任何标签)。 为了帮助可视化正在发生的事情,模型角色非常类似于表格的列,其中行条目对应于模型项:
import QtQuick 1.1

Rectangle {
    width: 360
    height: 360
    /* ------------------- */
    GridView {
        id: grid_view1
        anchors.centerIn: parent
        width: 140; height: 140
        cellHeight: 70
        delegate: delegateItem
        model: testqml // the C++ model is set here
        cellWidth: 70;
    }
    /* ------------------- */
    Component {
        id: delegateItem
        Item {
            x: 5; height: 50
            Column {
                spacing: 5
                Rectangle {
                    width: 40; height: 40;
                    color: Color // Note: this a role defined in the C++ model
                    anchors.horizontalCenter: parent.horizontalCenter
                }
                Text {
                    x: 5;
                    text: Name // Note: this is another role defined in the C++ model
                    anchors.horizontalCenter: parent.horizontalCenter
                    font.bold: true
                }
            }
        }
    } // end delegateItem

} // end Rectangle

然后我的main.cpp与你的几乎相同,我会将其发布以避免任何混淆:

#include "qtquick1applicationviewer.h"
#include <QApplication>
#include "testname.h"
#include <QDeclarativeContext>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    testname *test = new testname();
    QtQuick1ApplicationViewer viewer;
    viewer.rootContext()->setContextProperty("testqml",test);

    viewer.addImportPath(QLatin1String("modules"));
    viewer.setOrientation(QtQuick1ApplicationViewer::ScreenOrientationAuto);
    viewer.setMainQmlFile(QLatin1String("qml/QMLSetProperty/main.qml"));
    viewer.showExpanded();

    return app.exec();
}

希望这能帮到你!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接