通过 id 访问 QML 槽中的嵌套对象(从 C++ 调用)
Access nested object in QML slot by id (called from c++)
我曾经有这样的安排 window 其中有一个文本字段,更新了从 c++ 发出的数据:
Window{
id: root
function qmlSlot(a){
_textField1.text=a;
}
TextField{
id: _textField1
}
}
绑定是这样的:
QQuickWindow *window=qobject_cast<QQuickWindow*>(topLevel);
QObject::connect(src,SIGNAL(someSignal(QVariant)),window,SLOT(qmlSlot(QVariant)));
现在我在主 window 中添加了更多东西(选项卡),但事情不再直接工作了。
A:当我将 qmlSlot
留在 Window 范围内时,它看不到 _textField1
:
Window{
id: root
function qmlSlot(a){
_textField1.text=a;
}
TabView{
Tab{
TextField{
id: _textField1
}
}
}
}
这给了我:
qrc:/main.qml:32: ReferenceError: _textField1 is not defined
B:当我将插槽本身移动到 _textField1
的范围时,我不知道如何从 c++ 绑定到它:
Window{
id: root
TabView{
Tab{
function qmlSlot(a){
_textField1.text=a;
}
TextField{
id: _textField1
}
}
}
}
导致:
QObject::connect: No such slot QQuickWindowQmlImpl_QML_21::qmlSlot(QVariant)
如何在访问嵌套项时从 C++ 调用 qmlSlot
(在本例中为 _textField
)?是否可以在我决定更改 window 布局时不必更改绑定代码?
我以前从来没有用过QML,但是docs建议你需要给每个对象的id
属性赋值,这样你就可以引用它了。我认为以下应该可行(但尚未测试)。
Window{
id: root
function qmlSlot(a){
mytabview.mytab._textField1.text=a;
}
TabView{
id: mytabview
Tab{
id: mytab
TextField{
id: _textField1
}
}
}
}
您的问题是 Tab
实际上是 Loader
,因此这意味着您的 TextField 是按需在另一个上下文中创建的。当您的 Tab
未激活时,没有 TextField
可访问。
您可以使用 tab.item
访问您的文本字段,但它仅在加载选项卡时有效。
虽然你有一个更深层次的问题,从 C++ 访问 QML 对象是不好的做法,因为这意味着你的业务层必须知道你的 UI 层。如果您想重构 UI,那可不好。相反,您应该做的是从 QML 中的 C++ 中提取数据。更多解释在这里:Interacting with QML from C++.
在你的情况下,我会创建一个带有 属性 或信号的 QObject
子类(它是你的对象的状态还是事件?)。
然后使用 setContextProperty
使您的对象实例之一可用于 QML 引擎。
在您的 QML 中,您只需执行(如果它是 属性):
Window{
id: root
TabView{
Tab{
TextField{
text: myCppObject.textProperty
}
}
}
}
我曾经有这样的安排 window 其中有一个文本字段,更新了从 c++ 发出的数据:
Window{
id: root
function qmlSlot(a){
_textField1.text=a;
}
TextField{
id: _textField1
}
}
绑定是这样的:
QQuickWindow *window=qobject_cast<QQuickWindow*>(topLevel);
QObject::connect(src,SIGNAL(someSignal(QVariant)),window,SLOT(qmlSlot(QVariant)));
现在我在主 window 中添加了更多东西(选项卡),但事情不再直接工作了。
A:当我将 qmlSlot
留在 Window 范围内时,它看不到 _textField1
:
Window{
id: root
function qmlSlot(a){
_textField1.text=a;
}
TabView{
Tab{
TextField{
id: _textField1
}
}
}
}
这给了我:
qrc:/main.qml:32: ReferenceError: _textField1 is not defined
B:当我将插槽本身移动到 _textField1
的范围时,我不知道如何从 c++ 绑定到它:
Window{
id: root
TabView{
Tab{
function qmlSlot(a){
_textField1.text=a;
}
TextField{
id: _textField1
}
}
}
}
导致:
QObject::connect: No such slot QQuickWindowQmlImpl_QML_21::qmlSlot(QVariant)
如何在访问嵌套项时从 C++ 调用 qmlSlot
(在本例中为 _textField
)?是否可以在我决定更改 window 布局时不必更改绑定代码?
我以前从来没有用过QML,但是docs建议你需要给每个对象的id
属性赋值,这样你就可以引用它了。我认为以下应该可行(但尚未测试)。
Window{
id: root
function qmlSlot(a){
mytabview.mytab._textField1.text=a;
}
TabView{
id: mytabview
Tab{
id: mytab
TextField{
id: _textField1
}
}
}
}
您的问题是 Tab
实际上是 Loader
,因此这意味着您的 TextField 是按需在另一个上下文中创建的。当您的 Tab
未激活时,没有 TextField
可访问。
您可以使用 tab.item
访问您的文本字段,但它仅在加载选项卡时有效。
虽然你有一个更深层次的问题,从 C++ 访问 QML 对象是不好的做法,因为这意味着你的业务层必须知道你的 UI 层。如果您想重构 UI,那可不好。相反,您应该做的是从 QML 中的 C++ 中提取数据。更多解释在这里:Interacting with QML from C++.
在你的情况下,我会创建一个带有 属性 或信号的 QObject
子类(它是你的对象的状态还是事件?)。
然后使用 setContextProperty
使您的对象实例之一可用于 QML 引擎。
在您的 QML 中,您只需执行(如果它是 属性):
Window{
id: root
TabView{
Tab{
TextField{
text: myCppObject.textProperty
}
}
}
}