在 C++ 中循环读取 QML 对象(CheckBox)属性:总是相同的值

Posted

技术标签:

【中文标题】在 C++ 中循环读取 QML 对象(CheckBox)属性:总是相同的值【英文标题】:Reading QML object (CheckBox) property in a loop in C++: always the same value 【发布时间】:2020-03-11 03:30:26 【问题描述】:

我编写了一个简单的代码,在 C++ 循环中从我的 QML 中读取复选框的值。但是,我总是得到“未选中”的值,即使在我用鼠标切换复选框之后也是如此。

QML:

CheckBox 
    objectName: "simulatorCheckbox"
    text: "text"

C++:

QObject *rootObject = engine.rootObjects().first();
QObject *simulatorCheckboxQ = rootObject->findChild<QObject*>("simulatorCheckbox");
if (!simulatorCheckboxQ) 
    std::cout << "simulatorCheckboxQ not found" << std::endl;
    std::exit(1);


auto consume = [&simulatorCheckboxQ]() 
    while(true) 
        QVariant simulatorCheckboxState = simulatorCheckboxQ->property("checkedState");
        int simulatorCheckboxStateInt = simulatorCheckboxState.toInt();
        if (simulatorCheckboxStateInt==Qt::Unchecked) 
            std::cout << "UNchecked!" << std::endl;
         else if (simulatorCheckboxStateInt==Qt::Checked) 
            std::cout << "checked!" << std::endl;
         else if (simulatorCheckboxStateInt==Qt::PartiallyChecked) 
            std::cout << "PARTIALLY checked!" << std::endl;
        
        //delay...
    
;
//run consume as thread

【问题讨论】:

为什么需要while循环? 【参考方案1】:

你有两个不好的做法:

不要从 C++ 访问 QML 元素,因为这可能很危险。

你不应该使用while循环,还要考虑最后一个选项线程。

在这种情况下,GUI 不是线程安全的,因此从辅助线程访问此信息是危险的。在这种情况下,只需创建一个映射 CheckBox 更改的 QObject:

ma​​in.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QDebug>

class CheckBoxMapper: public QObject
    Q_OBJECT
    Q_PROPERTY(Qt::CheckState state READ state WRITE setState NOTIFY stateChanged)
public:
    using QObject::QObject;
    Qt::CheckState state() const
        return m_state;
    
public slots:
    void setState(Qt::CheckState state)
        if (m_state == state)
            return;
        m_state = state;
        emit stateChanged(m_state);
    
signals:
    void stateChanged(Qt::CheckState state);
private:
        Qt::CheckState m_state;
;

int main(int argc, char *argv[])

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    CheckBoxMapper checkboxMapper;
    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("checkboxMapper", &checkboxMapper);
    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);

    QObject::connect(&checkboxMapper, &CheckBoxMapper::stateChanged, [](Qt::CheckState state)
        qDebug() << state;
    );

    return app.exec();

#include "main.moc"

ma​​in.qml

CheckBox 
    text: "text"
    onCheckStateChanged: checkboxMapper.state = checkState
    Component.onCompleted: checkboxMapper.state = checkState

【讨论】:

QML 属性是“线程安全的”吗?因为这里***.com/questions/9062189/… 说我可以从 C++ 中设置它们 @LucasZanella 不,它们不是线程安全的。因此,不幸的是,他们有许多采用不良做法的答案。 我收到pastebin.com/uY1MSHZs 我做错了吗? 我没有使用 qmake,而是使用 cmake。我清理了所有内容并重建了所有内容,但仍然出现这些错误。 *** 上关于这个的所有答案似乎都依赖于人们忘记放 Q_OBJECT,这里不是这样 唯一的区别是我没有在main2.cpp的末尾添加#include "main2.moc",因为它抱怨这个文件不存在

以上是关于在 C++ 中循环读取 QML 对象(CheckBox)属性:总是相同的值的主要内容,如果未能解决你的问题,请参考以下文章

QML:如何从 C++ 中读取 QList

如何在 QML 中访问 C++ 类对象,而不是在 QML 中创建单独的对象?

在 QML 中创建自定义 C++ 对象并将其存储在 C++ 模型中

如何在 QML 中编辑 QQmlListProperty

从 QML 简单访问 C++ 对象数据

如何在 C++ 代码中的一些“繁重”操作之前使 QML 对象可见