可以在C++ QObject :: connect()中连接QML Object现有信号吗?

Jho*_*iro 1 c++ qt signals-slots qml

QML TreeView有一个名为:doubleClicked(QModelIndex)的信号

ref:https://doc.qt.io/qt-5.10/qml-qtquick-controls-treeview.html#doubleClicked-signal

它可能连接C++ QObject :: connect()中的现有信号?

我试过这个:

QQmlApplicationEngine engine;
QObject *myTreeMenu = engine.rootObjects().at(0)->findChild<QObject*>("myTreeMenu");
connect(myTreeMenu , SIGNAL(doubleClicked(QModelIndex)), this, SLOT(slotModelClicked(QModelIndex)));
Run Code Online (Sandbox Code Playgroud)

但我收到此返回错误:

QObject::connect: No such signal TreeView_QMLTYPE_63_QML_68::doubleClicked(QModelIndex) in '...'
QObject::connect:  (sender name:   'myTreeMenu ')
Run Code Online (Sandbox Code Playgroud)

Mit*_*tch 5

Qt 5.11文档解释了为什么这不是使用C++和QML的最佳方式.我建议你改为暴露一个插槽或Q_INVOKABLE在你的C++对象中并在onDoubleClicked处理程序中调用它:

Q_INVOKABLE void doStuff();
Run Code Online (Sandbox Code Playgroud)

在QML中:

onDoubleClicked: cppObject.doStuff()
Run Code Online (Sandbox Code Playgroud)

该文档有一个"之前和之后"的例子来证明这一点; 这是其中的大部分:

通过这种方法,可以从QML"拉出"对象的引用.这个问题是C++逻辑层依赖于QML表示层.如果我们以对象名称发生变化的方式重构QML,或者某些其他更改破坏了C++查找QML对象的能力,那么我们的工作流程变得更加复杂和繁琐.

重构QML比重构C++容易得多,因此为了使维护无痛,我们应该尽可能地保持C++类型不了解QML.这可以通过将对C++类型的引用"推送"到QML中来实现:

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    Backend backend;

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("backend", &backend);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}
Run Code Online (Sandbox Code Playgroud)

然后QML直接调用C++插槽:

import QtQuick 2.11
import QtQuick.Controls 2.4

Page {
    Button {
        text: qsTr("Restore default settings")
        onClicked: backend.restoreDefaults()
    }
}
Run Code Online (Sandbox Code Playgroud)

使用这种方法,如果将来需要重构QML,C++将保持不变.

在上面的示例中,我们在根上下文中设置了一个context属性,以将C++对象公开给QML.这意味着该属性可供引擎加载的每个组件使用.对于必须在加载QML时必须可用且不能在QML中实例化的对象,上下文属性非常有用.

集成QML和C++演示了一种替代方法,使QML知道C++类型,以便它可以自己实例化它.