通过id访问QML插槽中的嵌套对象(从c ++调用)

时间:2018-08-10 07:45:20

标签: c++ scope qml signals-slots qt-signals

我以前是这样安排一个窗口的,其中有一个文本字段,并使用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)));

现在,我在主窗口中添加了更多内容(标签),而这些内容不再能直接工作了。

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)

在访问嵌套项目(在这种情况下为qmlSlot)时如何从c ++调用_textField?可以决定是否要更改窗口布局时不必更改绑定代码吗?

2 个答案:

答案 0 :(得分:2)

您的问题是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
            }
        }
    }
}

答案 1 :(得分:-1)

我以前从未使用过QML,但是docs建议您需要为每个对象的id属性分配一个值,以便您可以引用它。我认为以下方法应该有效(但尚未测试)。

Window{
   id: root
   function qmlSlot(a){
      mytabview.mytab._textField1.text=a;
   }
   TabView{
      id: mytabview
      Tab{
         id: mytab
         TextField{
            id: _textField1
         }
      }
   }
}