属性绑定稍后会更新事件框架

时间:2018-10-23 14:39:46

标签: qt qml

我有一个暴露于QML的C ++对象,myObject。此C ++对象具有Q_PROPERTY

Q_PROPERTY (bool myProperty READ getMyPropert NOTIFY myPropertyChanged)

在QML中,我将其用作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;
};

MyClass.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();
}

main.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,则可以使用。如果您使用另一个,则无法使用。

1 个答案:

答案 0 :(得分:0)

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

此更新按以下顺序工作:

myClassChanged->设置:m_MyProperty_1(C ++)->信号myProperty_1Changed(QML)->过渡并触发后卫,然后->设置:m_MyProperty_2( C ++)->信号m_MyProperty_2Changed(QML)

所以myProperty_1myProperty_2比赛。