在 C++ 中从 QML 读取值
Posted
技术标签:
【中文标题】在 C++ 中从 QML 读取值【英文标题】:Reading value from QML in C++ 【发布时间】:2020-02-18 08:21:22 【问题描述】:我正在尝试从c++
上的QML
一侧读取int value
,但该值仍然是0
并且不会在c++
一侧更新,而console.log()
清楚地告诉我它在之后递增每次点击。我在这里做错了什么?
.qml 文件
FocusScope
property alias myrecordint: startbutton.recordint
Rectangle
id: buttonPaneShadow
width: bottomColumn.width + 16
height: parent.height
anchors.top: parent.top
anchors.right: parent.right
color: "white"
Column
anchors
right: parent.right
top: parent.top
margins: 8
id: buttonsColumn
anchors.rightMargin: 20
anchors.topMargin: 20
spacing: 12
CameraButton
id: startbutton
property int recordint:0
text: "Record"
visible: camera.videoRecorder.recorderStatus == CameraRecorder.LoadedStatus
onClicked:
recordint=recordint+1
camera.videoRecorder.record()
console.log(recordint)
.cpp 文件
QQmlEngine engine;
QQmlComponent component(&engine, QUrl("qrc:/VideoCaptureControls.qml"));
QObject *object = component.create();
qDebug() << "Property value:" << QQmlProperty::read(object, "myrecordint").toInt();
【问题讨论】:
将 c++ 暴露给 qml 是一种非常糟糕的方式,反之亦然。 Qt 已经提供了一种将您的 c++ 类与 qml 对象连接起来的方法,请在开发应用程序之前阅读此处doc.qt.io/qt-5/qtqml-cppintegration-exposecppattributes.html。 @arnes 非常感谢你,我一定会通过那个链接!我在 QML 方面没有太多经验,但这有帮助! 不客气,如果你卡在某个地方,你可以看看例子doc.qt.io/qt-5/qmlextendingexamples.html doc.qt.io/qt-5/qtqml-referenceexamples-adding-example.html 实际上这个例子展示了如何做到这一点。声明和定义 Person 类。在 main.cpp 之后,在调用engine.load( "your_qml.qml" )
之前,添加这段代码,qmlRegisterType<Person>( "your_module_name" , 1 /*major version of your module*/ , 2 /*minor version of your module*/ , "Person" /*Qml type name*/ );
,这样它就告诉 qml 引擎将 Person
类暴露给 qml
端。您可以访问您的属性,也可以从 qml 端调用 public slots:
函数
@arnes 好的!非常感谢!我会玩,看看我能不能成功!
【参考方案1】:
编辑
在来回评论之后,您似乎没有使用您应该使用的实例,因为您是在单击按钮时创建一个新实例。
此外,属性的读取是一次性执行的,不会自动更新。
总而言之,这是一个经典的 XY problem,您应该努力使用 Arnes 指出的 C++ 模型(example 1 和 example 2)
原始答案(错误,因为属性 是***的)
您只能从 QML 对象的顶层读取属性(从对象外部读取时)。您应该按照以下建议移动该属性:
Rectangle
id: buttonPaneShadow
width: bottomColumn.width + 16
height: parent.height
anchors.top: parent.top
anchors.right: parent.right
color: "white"
property int recordint:0 //move to here
Column
anchors
right: parent.right
top: parent.top
margins: 8
id: buttonsColumn
anchors.rightMargin: 20
anchors.topMargin: 20
spacing: 12
CameraButton
id: startbutton
text: "Record"
visible: camera.videoRecorder.recorderStatus == CameraRecorder.LoadedStatus
onClicked:
recordint=recordint+1
camera.videoRecorder.record()
console.log(recordint)
就个人而言,我不喜欢您似乎实现这一点的方式。我宁愿选择具有可更新属性的 C++ 模型,但这取决于你
【讨论】:
如果问的不是太多,您是否也请给我这样一个c++模型的参考?就我个人而言,我不喜欢我选择的方法,或者我只是这样做,因为我不知道其他方法:) @Raad 我看到你已经得到了关于 C++ 模型的提示。回答您的另一个问题:您的属性不是 qml 文件的顶层(假设这是您在附加的 .cpp 文件中加载的那个),因为它位于您的 qml 文件创建的组件之一中 @Raad 那么这很有趣......除了使用 C++ 模型的建议之外,我想了解为什么这会失败,因为它实际上不应该。你能告诉你什么时候在 C++ 代码中读取属性吗? (在.cpp sn-p中加载后连续或仅一次) 这意味着您每次点击都会创建一个新的VideoCaptureControls
?在这种情况下,难怪你总是读 0,你绝对应该遵循 C++ 模型路线;-)
这是一次性执行,是的,但很可能您没有读取您认为应该读取的值(我假设您有一个正在运行的 qml gui,并且每次都在创建一个不可见的对象你点击你的QPushButton)。关于可能性:您可能有机会获得更改后的信号,以便您可以读取新值,或者您可以基于 QTimer 执行此操作,但实际上:不要 ;-) 【参考方案2】:
这里是从 c 读取 qml 数据的代码示例
QObject *rootObject = engine.rootObjects().first();
QObject *pageOne = rootObject->findChild<QObject*>("page1box");
//calling qml function from c
QVariant returnedValue;
QVariant msg = "Hello from C++";
QMetaObject::invokeMethod(pageOne, "myQmlFunction",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, msg));
qDebug() << "QML function returned:" << returnedValue.toString();
【讨论】:
以上是关于在 C++ 中从 QML 读取值的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 C++ 中从标准输入读取行比 Python 慢得多?