我正在尝试编写一个插件,其中包含一些 QML 文件和一些提供较低级别功能并与另一个应用程序通信的 C++ 类。它们由 QML 组件使用。 我希望能够从 QML 管理这些 C++ 对象的生命周期(即它们应该在加载 QML 文件时创建并在 QML 销毁时销毁),同时仍然能够模拟 C++ 对象。
到目前为止,我尝试了几种不同的方法。理想情况下,结果是我可以在要编辑的 QML 文件上使用 qmlscene
,并在该文件旁边有一个 dummydata
文件夹,其中包含实例化 C++ 的模拟类(class)。
如果我尝试在继承自 QQmlExtensionPlugin
的插件类中使用 qmlRegisterType
(类似于 https://qmlbook.github.io/ch17-extensions/extensions.html 中的示例),并将生成的库传递给 qmlscene
,QML 文件不会使用 mock,而是实例化一个 C++ 对象。这意味着有时,我需要启动一些逻辑来将一些模拟数据放入我的 QML 文件中。
“QML Book”中的示例似乎建议在将任何 C++ 引入 QML 之前,先使用 mock 完全设计 QML 组件。有没有办法做到这一点更可持续?我想,我可以通过注释掉相应的行来避免将 qmlRegisterType
用于我想模拟一段时间的 C++ 类,但我不想这样做。
我尝试的另一种方法是使用中央 C++ Controller 类中的 QQMLContext::setContextProperty
。这使我能够将 C++ 对象从 C++ 传递到 QML 并使用虚拟数据,但是对象的生命周期不会由 QML 组件管理,而是由 C++ 管理。此外,每个类都应该被多次实例化,正确连接信号很容易出错。这是我到目前为止发现的:
auto proxy = std::make_shared<Proxy>();
//make `proxy` object known in QML realm
_qmlEngine.rootContext()->setContextProperty("proxy", proxy.get());
connect(&_qmlEngine, &QQmlApplicationEngine::objectCreated,
[&proxy](QObject *object, const QUrl &url) {
if (url == QUrl("qrc:/imports/Common/TestWindow.qml")) {
// make sure the proxy is not destroyed when leaving scope of this function
connect(qobject_cast<QQuickWindow *>(object),
&QWindow::visibilityChanged, // as a dirty workaround for missing QWindow::closing signal
[proxy]() mutable { proxy.reset(); }); // delete proxy when closing TestWindow
}
});
_qmlEngine.load(QUrl("qrc:/imports/Common/TestWindow.qml"));
是否有一种“舒适”的方式来模拟在 QML 中实例化且最初来自 C++ 的数据,或者至少有一种好方法可以将此类 C++ 对象的生命周期附加到 QML 对象的生命周期?
最佳答案
我解决这个问题的方法如下:
实际生产应用程序将使用 C++ 插件,仅包含 C++ 文件,不包含 QML。
对于模拟,有一个与 C++ 插件同名的 QML 模块,其中包含提供与等效 C++ 类相同接口(interface)的 QML 文件。除了一般的 QML 包含之外,这个模块被传递给 qmlscene
。
如果 C++ 类头如下所示:
class Proxy : public QObject
{
Q_OBJECT
public:
Q_PROPERTY(int foo)
Q_INVOKABLE void start();
signals:
void started();
}
并且此类可用于 QML,如下所示:
qmlRegisterType<Proxy>("Logic", 1, 0, "Proxy");
QML 模拟(在文件 Proxy.qml
中)看起来像这样:
import QtQml 2.12
QtObject {
signal started()
property var foo: 42
function start() { console.log("start") }
}
并且可以使用如下所示的 qmldir
文件在 QML 中导入:
module Logic
Proxy 1.0 Proxy.qml
qmlscene
的最终调用将是
qmlscene [path/to/prototype/qml] -I [path/to/folder/containing/proxy/mock/]
关于c++ - 模拟在 QML 中实例化的 C++ 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58660958/