如何从 Qml Checkbox 获取初始值到 C++?

问题描述

我有 qtquick 前端和 C++ 后端。在 Qml 中,我有一个带有随机初始值的复选框。我有一个从未收到过的 onCheckedChanged 发出的信号。我相信,这是因为该组件是在进行连接语句之前创建的。当用户交互时,我可以捕获这些事件,但我错过了初始值。我不能更快地建立连接,因为 QMl 引擎必须首先创建组件,以便我可以参考它们来建立信号槽连接。那么如何找出初始值呢?我是否必须制作一个计时器,它会在启动后几秒钟发出值?有没有更好的办法?

这里是最小的例子(当初始值为真时,插槽永远不会被触发)

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
applicationwindow {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")
    signal checkBoxStateChanged(enabled: bool)
    CheckBox{
        checked: Math.random() > 0.5
        text: "value"
        onCheckedChanged: checkBoxStateChanged(checked)
    }
}

后端.h

#include <QObject>
#include <QDebug>
class Backend: public QObject{
    Q_OBJECT
public:
    Backend(){}
public slots:
    void logChecked(bool checked){
        qDebug()<<checked;
    }
};

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QObject>
#include "backend.h"
int main(int argc,char *argv[])
{
    QGuiApplication app(argc,argv);
    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine,&QQmlApplicationEngine::objectCreated,&app,[url](QObject *obj,const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    },Qt::QueuedConnection);
    engine.load(url);
    const auto root=engine.rootObjects();
    QObject *window = root[0];
    Backend b;
    QObject::connect(window,SIGNAL(checkBoxStateChanged(bool)),&b,SLOT(logChecked(bool)));
    return app.exec();
}

解决方法

我不确定您正在尝试的方法,但更简洁的方法是将 QML 检查值绑定到 c++ 类。然后您可以处理后端类中的所有内容,这更容易调试和维护。所以使用你的例子,

#include <QObject>
#include <QDebug>
class Backend: public QObject{
    Q_OBJECT
    // Add a Q_PROPERTY to bind in QML
    Q_PROPERY(Qt::CheckState checked READ getChecked WRITE setChecked NOTIFY checkedChanged)
signals:
    void checkedChanged();
public:
    Backend() { m_checked = <random_value>;}

    // implement the q_property methods
    void setChecked(const Qt::CheckState value) {
        if (m_checked != value) {
             m_checked = value;
             emit checkedChanged();
        }
    }
    Qt::CheckState getChecked() const { return m_checked; }
public slots:
    void logChecked(bool checked){
        qDebug()<<checked;
    }

private:
   m_checked;
};

然后在 QML 中:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQml 2.12 // Binding
import Backend 1.0

ApplicationWindow {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")
    signal checkboxStateChanged(enabled: bool)
    
    CheckBox{
        id: qmlCheckBox
        checked: backend.checked // C++ to QML binding
        text: "value" // you can bind this too
    }

    // QML to C++ binding
    Binding {
        target: backend
        property: "checked"
        value: qmlCheckBox.checked
    }
}

在 main.cpp 中:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QObject>
#include "backend.h"
int main(int argc,char *argv[])
{
    QGuiApplication app(argc,argv);
    QQmlApplicationEngine engine;

    // Register backend class for qml
    qmlRegisterType<Backend>("Backend",1,"Backend");
    engine.rootContext()->setContextProperty("backend",new Backend);


    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine,&QQmlApplicationEngine::objectCreated,&app,[url](QObject *obj,const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    },Qt::QueuedConnection);
    engine.load(url);
    
    return app.exec();
}