【发布时间】:2020-12-21 22:21:51
【问题描述】:
在将此标记为“无法在 QQmlPropertyMap 的子类中从 QML 调用 slot 或 Q_INVOKABLE”的副本之前,请阅读最终回复 (https://stackoverflow.com/a/18674363/447438)。
我正在设计一个继承自 QQmlPropertyMap 的类(称为 MyBaseClass)。它为我的系统实现了一些额外的行为,然后被其他从MyBaseClass(例如ChildClass)初始化的类使用。
我希望从 QML (QtQuick) 调用 ChildClass 的插槽 (mySlot())。当我尝试时,即使我只使用ChildClass,我也会在应用程序输出中遇到以下问题(提到MyBaseClass)。
qrc:/main.qml:17: TypeError: Property 'mySlot' of object MyBaseClass(0x55f88ef86b50) is not a function
qrc:/main.qml:24: TypeError: Property 'mySlot' of object MyBaseClass(0x55f88ef86b50) is not a function
我也尝试实现从 QML 发送信号,但在尝试绑定到 QML 发出的信号时遇到了类似的问题。 (我没有添加那个例子。)
对于那些建议我只是将 QQmlPropertyMap 继承到 ChildClass 中的人(除了 MyBaseClass 已经通过受保护的方法对其进行了适当的继承和初始化),结果并不漂亮:
/home/jwerner/Projects/InheritanceTest-simple/ChildClass.h:8: warning: direct base 'QQmlPropertyMap' is inaccessible due to ambiguity:
class ChildClass -> class MyBaseClass -> class QQmlPropertyMap
class ChildClass -> class QQmlPropertyMap
我的“直觉”说问题在于我没有按照“Qt 方式”做事,但我不知道它是什么。
这是演示问题的最小示例代码。 (我省略了 .pro 文件,因为制作起来很简单。)
MyBaseClass.h
#include <QQmlPropertyMap>
class MyBaseClass : public QQmlPropertyMap
{
Q_OBJECT
public:
explicit MyBaseClass(QObject *parent = nullptr)
: QQmlPropertyMap(this, parent)
{}
};
ChildClass.h
#include "MyBaseClass.h"
#include <QObject>
#include <QDebug>
class ChildClass : public MyBaseClass
{
Q_OBJECT
public:
ChildClass(QObject *parent = nullptr)
: MyBaseClass(parent) {}
public slots:
void mySlot() {
qDebug() << "This is mySlot";
};
};
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
id: theMainWindow
width: 640
height: 480
visible: true
title: qsTr("Hello World")
property QtObject cData: childData;
onCDataChanged: {
childData.mySlot();
}
Timer { // wait a bit before calling
repeat: false
interval: 2000
running: true
onTriggered: childData.mySlot();
}
}
main.cpp
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
auto childData = new ChildClass();
engine.rootContext()->setContextProperties({
QQmlContext::PropertyPair{"childData", QVariant::fromValue(childData)},
});
const QUrl url(QStringLiteral("qrc:/main.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();
}
【问题讨论】:
-
您提供的链接指向错误报告的链接,该报告链接回documentation,其中包括以下位:“注意:从 QQmlPropertyMap 派生类时,请使用受保护的双参数构造函数,以确保该类已正确注册到 Qt 元对象系统。"
-
JarMan,基类 (MyBaseClass) 已经在这样做了。尝试将 QQmlPropertyMap 的继承添加到 ChildClass 会导致错误。 “/home/jwerner/Projects/InheritanceTest-simple/ChildClass.h:8: 警告:由于歧义,直接基 'QQmlPropertyMap' 无法访问:Class ChildClass -> class MyBaseClass -> class QQmlPropertyMap class ChildClass -> class QQmlPropertyMap”跨度>
-
@jwernerny 你不能从 QObject 乘法派生,所以从
QQmlPropertyMap重新继承当然是行不通的,我确定这不是暗示。 -
“我正在设计一个继承自 QQmlPropertyMap 的类(称为 MyBaseClass)”——这就是问题的根源。 “Qt 方式”需要一个明确的答案,说明为什么这是必要的以及您想要实现的目标。也许这是一个不必要的并发症。如果属性不是动态创建的,
QQmlPropertyMap则根本不需要,在这种情况下,Qt 6 的可绑定属性会这样做。 -
我想做的是创建一种可重用的方式将数据从 C++ 接口层传递到 QML 显示层。我们交互的每个事物都有它自己的数据,并且可能有我们需要从 UI 触发的事物。我们还不知道事物的所有数据(而且它一直在变化),因此必须具备创建动态数据的能力。
标签: c++ qml qt5 qt-signals