首页 > 解决方案 > 属性绑定稍后更新事件框架

问题描述

我有一个暴露给 QML 的 C++ 对象作为myObject. 这个 C++ 对象有一个Q_PROPERTY

Q_PROPERTY (bool myProperty READ getMyPropert NOTIFY myPropertyChanged)

在 QML 中,我将其用作 a 中的守卫,SignalTransition如下所示:

property bool foo: myObject.myProperty

SignalTransition {
   targetState: someState
   signal: someSignal
   onTriggered: console.info("foo: " + foo)
   onTriggered: console.info("myObject.myProperty: " + myObject.myProperty)
}

输出如下:

foo: false
myObject.myProperty: true

稍后的事件框架也foo将变为true

这种行为正常吗?

编辑:

这是一个工作示例:

MyClass.h:

#pragma once

#include <QObject>

class MyClass : public QObject {
Q_OBJECT

    Q_PROPERTY(bool myProperty_1 READ getMyProperty_1 NOTIFY myClassChanged)
    Q_PROPERTY(bool myProperty_2 READ getMyProperty_2 NOTIFY myClassChanged)

public:
    static void initQML();

    MyClass();

    bool getMyProperty_1();
    bool getMyProperty_2();

    Q_INVOKABLE void setMyProperty(bool value);

signals:
    void myClassChanged();

private:
    bool m_MyProperty_1;
    bool m_MyProperty_2;
};

我的类.cpp:

#include "MyClass.h"

#include <QtQml>
#include <QDebug>
#include <QMetaType>

/*static*/ void MyClass::initQML() {
    qmlRegisterType<MyClass>("Test", 1, 0, "MyClass");
}

MyClass::MyClass() : m_MyProperty_1(false), m_MyProperty_2(false) {
    qDebug() << "Constructor called.";
}

bool MyClass::getMyProperty_1() {
    return m_MyProperty_1;
}

bool MyClass::getMyProperty_2() {
    return m_MyProperty_2;
}

void MyClass::setMyProperty(bool value) {
    m_MyProperty_1 = value;
    m_MyProperty_2 = value;
    myClassChanged();
}

主.cpp:

#include <QGuiApplication>
#include <QQmlApplicationEngine>

#include "MyClass.h"

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

    QGuiApplication app(argc, argv);

    // Init

    MyClass::initQML();

    // Main loop

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

    return app.exec();
}

main.qml:

import QtQuick 2.9
import QtQuick.Controls 2.2

import QtQml.StateMachine 1.0 as QtQml_StateMachine

import Test 1.0

ApplicationWindow {
    visible: true

    width: 480
    height: 272

    Component.onCompleted: _stateMachine.start()

    // UI

    Button {
        text: "Switch"

        onClicked: {
            console.info("Switch pressed with setter")
            myClass.setMyProperty(true)
        }
    }

    // StateMachine

    property MyClass myClass: MyClass {}

    QtQml_StateMachine.StateMachine {
        id: _stateMachine

        initialState: _defaultState

        onStarted: console.info("_stateMachine started")
        onExited: console.info("_stateMachine exited")

        QtQml_StateMachine.State {
            id: _defaultState

            property bool myProperty_1: myClass.myProperty_1
            property bool myProperty_2: myClass.myProperty_2

            onMyProperty_1Changed: console.info("onMyProperty_1Changed: " + myProperty_1)
            onMyProperty_2Changed: console.info("onMyProperty_2Changed: " + myProperty_2)

            onEntered: console.info("_defaultState entered")
            onExited: console.info("_defaultState exited")

            // Doesn't work:
            QtQml_StateMachine.SignalTransition {
                targetState: _nextState
                signal: _defaultState.myProperty_1Changed
                guard: _defaultState.myProperty_2
                onTriggered: console.info("myProperty_2")
            }

              // Works:
//            QtQml_StateMachine.SignalTransition {
//                targetState: _nextState
//                signal: _defaultState.myProperty_1Changed
//                guard: myClass.myProperty_2
//                onTriggered: console.info("myClass.myProperty_2")
//            }
        }

        QtQml_StateMachine.State {
            id: _nextState

            onEntered: console.info("_nextState entered")
            onExited: console.info("_nextState exited")
        }
    }
}

如果您使用评论SignalTransition它的工作原理。如果您使用另一个,它将无法正常工作。

标签: qtqml

解决方案


问题是存在竞争条件,因为代理 C++ 对象的属性以具有单独的Changed信号。这是由于 QML 中的直接连接。

更新按以下顺序进行:

myClassChanged-> 设置:m_MyProperty_1(C++) -> 信号myProperty_1Changed(QML) -> 转换并击中守卫,然后 -> 设置:m_MyProperty_2(C++) -> 信号m_MyProperty_2Changed(QML)

如此myProperty_1赛跑myProperty_2


推荐阅读