c++ - QML 计时器未触发
问题描述
我在 qml 中有一个计时器(在 StackView 中查看),我尝试从 C++ 代码开始,调用 javascript 函数。但我的计时器永远不会被触发。我究竟做错了什么?我的流程是 a.qml -> b.qml(点击按钮)
文件 b.qml:
Item {
function connectionConfirmed() {
myTimer.start()
console.log("started timer")
}
Timer {
interval: 1000; running: false; repeat: false
id: myTimer
onTriggered: {
console.log("timer triggered")
}
}
}
文件 main.qml:
ApplicationWindow {
id: root
visible: true
width: 320
height: 530
StackView {
id: stackView
initialItem: "qrc:/a.qml"
anchors.fill: parent
}
}
文件 a.qml
MouseArea{
anchors.fill: parent
onClicked: {
stackView.push("qrc:/b.qml")
}
}
C++部分:
connect(&myObjectInstance, &X::somethingHappend, this, [this](){
QQmlComponent component(&engine_, "qrc:/b.qml");
QObject *obj = component.create();
QVariant returnedValue;
QMetaObject::invokeMethod(obj, "connectionConfirmed",
Q_RETURN_ARG(QVariant, returnedValue));
delete obj;
});
输出是:
started timer
当我尝试设置running: true
定时器被触发时,是否意味着我无法从 JS 函数启动定时器?
解决方案
问题是因为您假设在 C++ 端创建的组件与在 QML 端创建的组件相同。.qml 文件是源代码,当您调用它时,它们每次都会生成不同的对象。
行为说明:
connect(&myObjectInstance, &X::somethingHappend, this, [this](){
QQmlComponent component(&engine_, "qrc:/b.qml");
QObject *obj = component.create();
QVariant returnedValue;
QMetaObject::invokeMethod(obj, "connectionConfirmed",
Q_RETURN_ARG(QVariant, returnedValue));
delete obj;
});
在这段代码中,您首先创建组件,然后创建对象,调用用js编写的函数,该函数刚刚执行并打印消息,然后您将其删除,所以当您删除它时,它会从不开火。new Timer,由于这个原因,打印第一条消息的似乎是在 QML 中创建的项目,但事实并非如此,新项目打印了它。
调用 C++ QML 函数会带来这些问题,因为很多时候您并没有访问您想要的对象。
相反,Qt 提出的建议是在 QML 端建立连接,为此您必须使用 .export 导出 C++ 对象setContextProperty()
。
在下面使用其 QML 实现的示例中,我们创建了一个类,该类具有一个名为 mysignal 的信号,它每 5 秒触发一次以进行测试。该类的一个对象被导出到 QML 并连接,以便它从 QML 调用 js 函数
主文件
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QTimer>
class Helper: public QObject{
Q_OBJECT
public:
using QObject::QObject;
signals:
void mysignal();
};
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
Helper helper;
engine.rootContext()->setContextProperty("helper", &helper);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, [&helper](){
emit helper.mysignal();
});
timer.start(5000);
return app.exec();
}
#include "main.moc"
b.qml
import QtQuick 2.0
Item {
id: it
function connectionConfirmed() {
myTimer.start()
console.log("started timer")
}
Timer {
interval: 1000; running: false; repeat: false
id: myTimer
onTriggered: {
console.log("timer triggered")
}
}
Connections{
target: helper
onMysignal: it.connectionConfirmed()
}
}
最后,在 StackView 中,每次更改页面时都会创建和销毁项目。
推荐阅读
- wso2esb - 当payloadFactory wso2 esb中的动态参数为空时如何跳过动态参数作为XML
- x86 - ptrace x86 函数蹦床
- javascript - [javascript webdriverIO} 从具有多个节点的 Xpath 中随机选择一个
- java - 不同目录中的 Java 类路径
- java - 无法使用带有休眠 3.3.2 的 C3p0 库连接到数据库
- java - 破弹簧安全增加了一个方面
- json - 如何将嵌套的 JSON 数据导入 Postman 的集合运行器?
- mysql - 如何从用户请求(MySQL)检查正在访问(未更新)的表
- c# - 当你对物体的边缘施加力时会发生什么?
- java - 重新启动后缺少意图“附加”值