[英]QML function invoked from C++ not able to update element
I am invoking a QML function from C++.我正在从 C++ 调用 QML 函数。 Issue is the QML function cannot update a QML element when invoked from C++.
问题是 QML 函数在从 C++ 调用时无法更新 QML 元素。 below is code:
下面是代码:
In main.qml
:在
main.qml
:
import QtQuick 2.0
function myQmlFunction(msg) {
console.log("Got message:", msg)
textbox.text = msg
return "some return value"
}
Text {
id: textbox
text: "nothing"
}
In main.cpp
:在
main.cpp
:
QQmlEngine engine;
QQmlComponent component(&engine, "MyItem.qml");
QObject *object = component.create();
QVariant returnedValue;
QVariant msg = "Hello from C++";
QMetaObject::invokeMethod(object, "myQmlFunction",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, msg));
qDebug() << "QML function returned:" << returnedValue.toString();
delete object;
The textbox element is just a regular text, and the text inside it remains "nothing", instead of the expected "Hello from C++". textbox 元素只是一个普通文本,其中的文本保持“无”,而不是预期的“Hello from C++”。
Any ideas on how to solve this issue or in successfully passing arguments from C++ to QML?关于如何解决这个问题或成功地将参数从 C++ 传递到 QML 的任何想法?
I'll assume that the qml code given actually belongs to MyItem.qml
instead of main.qml
.我假设给出的
MyItem.qml
代码实际上属于MyItem.qml
而不是main.qml
。
Your Qml file generated an compile-time error.您的 Qml 文件生成了编译时错误。 Functions should be placed inside an object, like so
函数应该放在一个对象里面,像这样
// MyItem.qml
import QtQuick 2.0
Text {
id: textbox
text: "nothing"
function myQmlFunction(msg) {
console.log("Got message:", msg)
textbox.text = msg
return "some return value"
}
}
I'm not sure how you were able to compile your project without generating an error, but I'm guessing either我不确定你是如何编译你的项目而不产生错误的,但我猜要么
I'm sure you have a sufficient understanding about Qml so I'm not going to go deep into this.我相信您对 Qml 有足够的了解,所以我不打算深入探讨。
On the C++ side, I had to fiddle around with debug output to see what's wrong.在 C++ 方面,我不得不摆弄调试输出以查看出了什么问题。 Here's my
main.cpp
:这是我的
main.cpp
:
// main.cpp
#include <QApplication>
#include <QDebug>
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include <QQuickItem>
int main(int argc, char *argv[])
{
QApplication app(argc, argv); // Qt requires an instance of QApplication
QQmlEngine *engine = new QQmlEngine;
QString projectPath = "/Users/user/full/path/to/your/project"; // I'm on a Mac, but replace
// with the appropriate path to your project
// QQmlComponent component(engine, "MyItem.qml"); // this didn't work for me and
// set component.status() to QQmlComponent::Error
QQmlComponent component(engine, projectPath + "/qml/MyItem.qml"); // use full path
qDebug() << "Status:" << component.status();
if (component.status() == QQmlComponent::Error)
qDebug() << "Errors:" << component.errors();
else if (component.status() != QQmlComponent::Ready)
{
qDebug() << "Component is not ready!";
return 0;
}
QObject *object = component.create();
if (!object) { qDebug() << "Object creation failed!"; return 0; }
QQuickItem *item = qobject_cast<QQuickItem*>(object); // adding this didn't change much
// but this could be crucial
QVariant returnedValue;
QVariant msg = "Hello from C++";
bool success = QMetaObject::invokeMethod(item, "myQmlFunction", // replace `object` with `item`
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, msg));
if (success)
qDebug() << "QML function returned:" << returnedValue.toString();
else
qDebug() << "QMetaObject::invokeMethod returned false";
delete object;
return 0;
}
The output I received on a successful build, with a successful object creation was我在成功构建并成功创建对象时收到的输出是
Status: QQmlComponent::Status(Ready)
Object: MyItem_QMLTYPE_0(0x7f8d4ae8b640)
qml: Got message: Hello from C++
QML function returned: "some return value"
I haven't yet checked whether the text changed in your Qml textbox
.我还没有检查你的 Qml
textbox
的文本是否发生了变化。 (Didn't bother to. It'll require more changes to the C++ code and this answer is already long enough. I was also confident that nothing'll go wrong, so ¯\\_(ツ)_/¯). (没有打扰。它需要对 C++ 代码进行更多更改,这个答案已经足够长了。我也有信心不会出错,所以¯\\_(ツ)_/¯)。
If you're meh about using a raw file path (eg /Users/whoami/ugly/looking/path
) in如果你是如何使用原始文件路径(例如MEH
/Users/whoami/ugly/looking/path
中)
QString projectPath = "/Users/user/full/path/to/your/project";
You can add this to your .pro
file:您可以将其添加到您的
.pro
文件中:
DEFINES += SOURCE_PATH=$$PWD
and set projectPath
to并将
projectPath
设置为
QString projectPath = QT_STRINGIFY(SOURCE_PATH);
This idea was borrowed from a forum thread .这个想法是从一个论坛帖子中借来的。
Throughout my answer, I have assumed that your project hierarchy resembles在整个回答中,我假设您的项目层次结构类似于
/./
|- myProject.pro
|- main.cpp
|- qml/
|- MyItem.qml
The essential thing is that you use your full path to your qml item.最重要的是你使用你的 qml 项目的完整路径。 If you do find another to reference it (maybe using
QUrl
?) then do post a comment about it.如果您确实找到了另一个引用它(也许使用
QUrl
?),那么请发表评论。
Check out the details section of the QQmlComponent
class and QQmlComponent::create
member function .查看
QQmlComponent
类和QQmlComponent::create
成员函数的详细信息部分。 Reading these led me to know which values to debug and what to look out for.阅读这些让我知道要调试哪些值以及要注意什么。
Thanks for helping out, I debugged it as well and the textbox.text was being overwritten with "Hello from C++" without the text in the window to be updated.感谢您的帮助,我也调试了它,并且 textbox.text 被“Hello from C++”覆盖,而窗口中的文本没有更新。
like eyllanesc suggested, I was creating a new engine object other than the already displayed window.就像 eyllanesc 建议的那样,我正在创建一个新的引擎对象,而不是已经显示的窗口。 (created elsewhere in the code)
(在代码的其他地方创建)
after referencing the same object, the problem was solved.引用同一个对象后,问题就解决了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.