从C++调用 QML 函数,并使用另一个 QML 对象作为参数



我有一个QML文件Dialog.qml它是ApplicationWindow的,Tab.qmlItem的。Dialog.qmlTabView哪些选项卡是由Tab.qml形成的。我想在 Qt 中创建Tab.qml,将其信号连接到 Qt 中的类并将该选项卡添加到 Dialog 中。以下是代码的相关部分:

//Tab.qml
Item {
    id: tb
    anchors.fill: parent
    //...here is signals and controls like RadioButtons and TextFields
}
//Dialog.qml
ApplicationWindow {
    visible: true
    title: "settings"
    flags: Qt.Dialog
    //...
    function addTabfromCpp(tab){
        frame.addTab("from c++", tab);
    }
    TabView {
        id:frame
        //...
    }
}

当函数参数是原始类型(通过 QVariant)时,我知道如何从Qt调用QML函数。但是当函数的参数QQuickWindow或其他参数并且无法从中创建QVariant时,如何调用函数?

您可以将 QML 对象 ID 作为函数参数传递即可。在C++这些工作是QObject *.此外,除了 ids 之外,您还可以使用 parent 属性或 children[indexOfChild] .请注意,您不会传递实际对象,因为这需要调用复制构造函数,并且对所有派生类禁用QObject复制,它通过引用传递,它在 JS 中使用 var 和 C++ 中使用 QObject* 。以类似的方式,您可以使用QObject*将对象传递给 QML。此外,您可能希望将自定义类型添加到带有 qRegisterMetaType()Q_DECLARE_METATYPE 的 Qt 元类型中,这将在 QML 中为您提供该类型的自动完成功能。

为了在 QML 上下文中公开C++函数,您需要将这些函数设置为QObject派生类的插槽或Q_INVOKABLE,实例化该类并使用setContextProperty()将其公开给 QML。

或者,您可以将该对象注册到 QML 引擎,以便对其进行实例化,甚至可以按照此示例在该对象的多个实例之间共享相同的数据。

编辑:好的,试试这个:

QML:

ApplicationWindow {
    objectName: "blah"
    //...
    function foo(obj) { console.log(obj) }
}

.CPP:

QObject * root = engine.rootObjects().at(0);
QMetaObject::invokeMethod(root, "foo", Q_ARG(QVariant, QVariant::fromValue(root)));

输出为

qml: ApplicationWindow_QMLTYPE_11_QML_12(0x4121e70, "blah")

看来你必须把它作为Q_ARG(QVariant, QVariant::fromValue(QObject*)传递

然而,TabView.addTab()期望的不是一个对象(它是Component的实例),而是一个组件,即一个对象的原型。

您可以做到这一点的一种方法是:

QObject * root = engine.rootObjects().at(0);
QQmlComponent comp(&engine, QUrl("qrc:/Test.qml"));
QMetaObject::invokeMethod(root, "addTab", Q_ARG(QVariant, QVariant::fromValue(&comp)));

最新更新