无法找出将信号从qml绑定到cpp插槽的正确方法

Aka*_*wal 1 c++ qt signals-slots qml

我正在使用QT 5.7.我的main.qml文件的根元素是'ApplicationWindow'(它总是强调可见,宽度和高度作为无效属性,即使它们有效.我想知道它的修复或正确的方法,因为我无法编辑它在设计师).这是它的代码:

ApplicationWindow {
visible: true
width: 640
height: 480
    Rectangle{
    signal mSend()
    anchors.fill: parent
        Button{
            id: bSend
                onClicked: {
                    parent.mSend()
                }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我试图以mSend这种方式将信号绑定到CPP插槽:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>
#include <QObject>
#include <QQuickView>
#include <QQuickItem>

class Chat: public QObject{
    Q_OBJECT

    public Q_SLOTS:
    void sendMessage(){
        qDebug() << "CPP SLOT sendMessage called";
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));

    QQuickView view(&engine, Q_NULLPTR);
    QObject *item = view.rootObject();
    Chat chat;
    if(item){
        qDebug() << "Item found";
        QObject::connect(item, SIGNAL(mSend()), &chat, SLOT(sendMessage()));
    }else{
        qDebug() << "item is null";
    }

    return app.exec();
}
#include "main.moc"
Run Code Online (Sandbox Code Playgroud)

但结果是Item is null.我一直在关注本指南,但我无法在QML中修改QMLApplicationEngine和ApplicationWindow.

TIA

注意:我正在使用,Q_SLOTS因为我也使用Boost来合并Socket IO库.

jpn*_*rmi 8

我强烈建议将您的Chat对象暴露给QML ,而不是挖掘QML对象并从C++中弄乱它们.这是QML和C++集成设计的工作方式.您有多种选择可供选择.无论哪种方式,您都可以Chat::sendMessage()直接从Button::onClicked信号处理程序调用.

QML类型

您可以使用注册Chat为QML类型qmlRegisterType(),因此您可以使用QML 创建实例.

  • main.cpp中:

    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        QGuiApplication app(argc, argv);
    
        qmlRegisterType<Chat>("foo.bar", 1, 0, "Chat"); // <==
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    
        return app.exec();
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • main.qml:

    import QtQuick 2.0
    import QtQuick.Controls 2.0
    import foo.bar 1.0
    
    ApplicationWindow {
        Chat {
          id: chat
        } 
    
        Button {
            onClicked: chat.sendMessage(...)
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

QML Singleton类型

您可以使用注册Chat为QML单例类型qmlRegisterSingletonType(),因此您可以方便地在QML中的任何位置访问相同的实例.

  • main.cpp中

    static QObject *chatInstance(QQmlEngine *engine, QJSEngine *)
    {
        return new Chat(engine);
    }
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        QGuiApplication app(argc, argv);
    
        qmlRegisterSingletonType<Chat>("foo.bar", 1, 0, "Chat", chatInstance); // <==
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    
        return app.exec();
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • main.qml

    import QtQuick 2.0
    import QtQuick.Controls 2.0
    import foo.bar 1.0
    
    ApplicationWindow {
        Button {
            onClicked: Chat.sendMessage(...)
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

上下文属性

如果必须Chat在C++中创建实例,则可以将其设置为QQmlContext::setContextProperty()用于QML引擎的根上下文的上下文属性.请注意,必须加载引用context属性的QML 之前设置该属性.

  • main.cpp中

    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
    
        Chat chat;
        engine.rootContext()->setContextProperty("chat", &chat); // <==
    
        engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    
        return app.exec();
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • main.qml

    import QtQuick 2.0
    import QtQuick.Controls 2.0
    
    ApplicationWindow {
        Button {
            onClicked: chat.sendMessage(...)
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)