通过 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
            }
        }
    }
}