c++ - Qt/QML 从 C++ 类为 GridView 设置属性

标签 c++ qt gridview qml

首先,我创建了一个带有成员函数的新 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-Function,将返回的字符串暴露给 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 和类保持不变)我得到这个错误:

ListElement: cannot use script for property value 
                     name: testqml 
                     ^ 

现在我卡住了。我发现了一个具有类似问题的已报告错误 #QTBUG-16289 ,但我不知道如何解决我的问题。有什么想法、操作方法、教程或其他方法可以解决我的问题吗?

谢谢和问候 :)

最佳答案

我运行了您的代码并重现了您的错误,但您最终想做什么?

您的委托(delegate)表明您想要从 C++ 中注入(inject)一些具有 namecolor 的模型项,否则,为什么要使用 GridView ,对吗?

如果情况并非如此,那么接下来的内容可能不会那么有用,或者它的某些变体可能有用。因此,我继续构建了一个我认为您可能想要完成的示例。

总而言之,在我的系统上,在创建任意数量的模型项(在本例中为 20 个)之后,可滚动的 GridView 委托(delegate)(在滚动范围的中间)看起来像这样:

enter image description here

正如我所说,您似乎想将一些来自 C++ 模型的 QString 项注入(inject)到 QML GridView 中,注意使用 GridView 意味着您想要一些元素。在大多数情况下,您会希望继承预定义的 Qt 模型,它会自动处理几个重要的细节,例如保持 QML View 与模型同步,并在删除项目或添加新项目时自动更新 View .

考虑到这一点,QAbstractListModel 是一个方便的类,您可以将其作为模型的基础(尽管这不是唯一的选择,请参阅帮助文件)。乍一看,建立这个模型可能会显得很复杂,所以我继续定义了一个最小版本,我希望它能说明你想做什么。

下面是模型的代码(注意:我将所有代码都放在 .h 文件中,因此不需要 .m 文件)。我还创建了一些“项目”以注入(inject)到模型中,为简单起见,使用了一个 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;

};

接下来是使用上面定义的C++模型的QML代码,在main.cpp中注册为“testqml”,然后通过GridView中的model:属性定义>。

请注意,在委托(delegate)中,模型的 Color 和 Name 属性被定义为上面类中的角色名称(这些可以是您喜欢的任何标签)。为了帮助可视化正在发生的事情,模型角色与表格的列非常相似,行条目对应于模型项:

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();
}

希望这对您有所帮助!

关于c++ - Qt/QML 从 C++ 类为 GridView 设置属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20775167/

相关文章:

c++ - Arduino C++ 将对象作为参数传递

c++ - : Bit, byte 和 int 哪个更有效?

c++ - 如何将 gmock 函数分配给特定的函数指针?

asp.net-mvc - 使用 ASP.Net MVC 2 和 Telerik MVC(2010 年第一季度)向 Telerik 网格添加编辑列

wpf - 具有动态定义的WPF GridView

c++ - 线程管理和与 boost::thread 的并行性

c++ - 从源代码构建 Qt 5.8 - 配置 : Unknown command line option '-c++11'

c++ - Qt,客户区点击信号

visual-studio-2008 - 在 QtCreator 中使用 OpenCV 2.3 和 Qt

asp.net - 通过 jQuery ajax 绑定(bind) GridView