我必须创建一个包含不同类型项目的 QML“画布”。我能够使其在 Qt 6.8 上运行,但我的代码必须也可以在 Qt 5.15 上运行。
我正在展示我的整个“概念验证”代码,其中包含的内容超出了最低限度 - 让您了解我真正需要的是这些项目,而不是它们的内容。
下面的代码包含 2 个小对象类型,具有共同的
QQuickItem
父级,一个包含各种项目的列表的类(可以在运行时更改,添加、删除和更改属性),一个用于显示的 qml Repeater
列表中的项目,以及将事物联系在一起的主要内容。
线路
property list<Item> myModel: Backend.model
给出错误:
QQmlApplicationEngine failed to load component
qrc:/mainProof.qml:17:34: Syntax error
后端.h:
#ifndef BACKEND_H
#define BACKEND_H
#include <QQmlEngine>
#include <private/qquicktext_p.h>
#include <private/qquickrectangle_p.h>
class TextItem : public QQuickText
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(QString itemType MEMBER m_itemType NOTIFY itemTypeChanged)
public:
TextItem() : QQuickText(Q_NULLPTR), m_itemType("TextItem") {
setText("TextItem"); setPosition(QPointF(10, 15)); setSize(QSizeF(100, 20)); }
signals:
void itemTypeChanged();
private:
QString m_itemType;
};
class RectangleItem : public QQuickRectangle
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(QString itemType MEMBER m_itemType NOTIFY itemTypeChanged)
public:
RectangleItem() : QQuickRectangle(Q_NULLPTR), m_itemType("RectangleItem") {
setPosition(QPointF(40, 120)); setSize(QSizeF(100, 50)); setColor(Qt::red); }
signals:
void itemTypeChanged();
private:
QString m_itemType;
};
class Backend : public QObject
{
Q_OBJECT
Q_PROPERTY(QList<QQuickItem *> model MEMBER m_model NOTIFY modelChanged)
QML_ELEMENT
QML_SINGLETON
public:
explicit Backend(QObject *parent = nullptr) : QObject{parent} {
m_model.append(new TextItem());
m_model.append(new RectangleItem());
RectangleItem *r = new RectangleItem(); r->setColor(Qt::green); r->setPosition(QPointF(180, 120)); m_model.append(r);
TextItem *t = new TextItem(); t->setPosition(QPointF(40, 200)); t->setText("SecondTextItem"); m_model.append(t);
}
virtual ~Backend() override {
for (QQuickItem *item : m_model) delete item;
}
signals:
void modelChanged();
private:
QList<QQuickItem *> m_model;
};
#endif // BACKEND_H
main.cpp:
#include "backend.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#define APP_URI "uri.dlitems"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
qmlRegisterSingletonType<Backend>(APP_URI, 1, 0, "Backend", [](QQmlEngine *, QJSEngine *) {
return new Backend();
});
qmlRegisterType<TextItem>(APP_URI, 1, 0, "MyTextItem");
qmlRegisterType<RectangleItem>(APP_URI, 1, 0, "MyRectangleItem");
const QUrl url(QStringLiteral("qrc:/mainProof.qml"));
QObject::connect(
&engine,
&QQmlApplicationEngine::objectCreated,
&app,
[url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
},
Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
mainProof.qml:
import QtQuick 2.12
import QtQuick.Window 2.1
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.0
import Qt.labs.qmlmodels 1.0
import uri.dlitems 1.0
ApplicationWindow {
id: proofRoot
visible: true
width: 1024
height: 545
property list<Item> myModel: Backend.model // Here I get error
Rectangle {
id: trouble
anchors {
top: parent.top
left: parent.left
right: parent.right
bottom: parent.bottom
margins: 20
}
Repeater {
anchors.fill: parent
anchors.margins: 20
model: proofRoot.myModel
delegate: DelegateChooser {
id: chooser
role: "itemType"
DelegateChoice { roleValue: "TextItem"; MyTextItem {
x: model.x
y: model.y
height: model.height
width: model.width
color: model.color
text: model.text
}
}
DelegateChoice { roleValue: "RectangleItem"; MyRectangleItem {
x: model.x
y: model.y
height: model.height
width: model.width
color: model.color
}
}
}
}
}
}
也尝试使该行也出现错误:
property list<QtObject> myModel: Backend.model // Qt 6 works, Qt 5 same syntax error
property list<var> myModel: Backend.model // even Qt 6 fails to get the delegates (with the errors shown below); Qt 5 still syntax error
property var myModel: Backend.model // Qt 5 accepts the list, but both Qt 5 and Qt 6 fail to get the delegates:
qrc:/mainProof.qml:45:25: Unable to assign [undefined] to QString
qrc:/mainProof.qml:44:25: Unable to assign [undefined] to QColor
qrc:/mainProof.qml:41:25: Unable to assign [undefined] to double
...
我也尝试过使用
Q_PROPERTY(QQmlListProperty<QQuickItem> model READ model NOTIFY modelChanged)
在 C++ 方面(及其所需的所有附加功能);与
QList
的行为相同
我尝试的任何方法似乎都无法使 Qt 5.15 正常工作。
任何平台;必须在 Qt 5.15 中工作(它在 Qt 6.8 中工作,可能是 6.4 以上的任何版本)
为了简单地交付列表,我通常最初使用 C++ 中的
QVariantList
进行原型设计,在 QML 方面,我使用 var
(Qt5.15) 或 list<var>
(Qt6.4+)。在委托中使用行时,请使用 modelData
。
对于需要行更改通知(添加、修改、删除)的大型列表,那么,当然,请考虑在 C++ 端使用
QQmlListProperty
,从 QML 端,您可以使用 var
(Qt5.15) 或list<your_item>
(Qt6.4+)侧。在委托中使用行时,请使用 model
。