首先,我创建了一个带有成员函数的新 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)一些具有 name
和 color
的模型项,否则,为什么要使用 GridView
,对吗?
如果情况并非如此,那么接下来的内容可能不会那么有用,或者它的某些变体可能有用。因此,我继续构建了一个我认为您可能想要完成的示例。
总而言之,在我的系统上,在创建任意数量的模型项(在本例中为 20 个)之后,可滚动的 GridView
委托(delegate)(在滚动范围的中间)看起来像这样:
正如我所说,您似乎想将一些来自 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/