c++qtqmlqqmlapplicationengine

QT Signal Documentation on Dial


I am struggling with this problem and I can find any solution. So I have this code for QML

Dial {
    id: volumeDial
    property int speedValue: volumeDial.value.toFixed(0)
    objectName: "speedDial"
    from: 0
    value: 42
    to: 100
    stepSize: 1
    Layout.alignment: Qt.AlignHCenter
    Layout.minimumWidth: 64
    Layout.minimumHeight: 64
    Layout.preferredWidth: 128
    Layout.preferredHeight: 128
    Layout.maximumWidth: 128
    Layout.maximumHeight: 128
    Layout.fillHeight: true
    Label {
        text: volumeDial.value.toFixed(0)
        horizontalAlignment: Text.AlignLeft
        fontSizeMode: Text.FixedSize
        color: "white"
        font.pixelSize: Qt.application.font.pixelSize * 3
        anchors.centerIn: parent
    }

My problem is that I want to store the value from the volumeDial.value in a int variable and after I moved the dial to update the int variable with the new volumeDial.value and so on. This is my .cpp code:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QSettings>
#include <QQuickStyle>
#include <QIcon>
#include <QDebug>
#include <QQmlProperty>
int main(int argc, char *argv[])
{
    QGuiApplication::setApplicationName("Automotive");
    QGuiApplication::setOrganizationName("QtProject");
    QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);

    QGuiApplication app(argc, argv);

    QIcon::setThemeName("automotive");

    QQmlApplicationEngine engine;
    engine.load(QUrl("qrc:/qml/automotive.qml"));
    if (engine.rootObjects().isEmpty())
        return -1;
    QObject *rootObject = engine.rootObjects().first();
    QObject *qmlObject = rootObject->findChild<QObject*>("speedDial");
  if(qmlObject)
  {
//      qDebug() << "Speed value:" << QQmlProperty::read(qmlObject, "speedValue").toInt();
       qDebug()<< qmlObject->property("value").toInt();
  }

    return app.exec();
}

Now I can get the initial value from the value.volumeDial but I want to get every value after I released the leftbutton click from the dial. In the Dial Signal Documentation there exists a function called moved() but I don't know how to use it and also I don't know if that function is the answer to my problem. I kindly ask you to show me with some code that can resolve my problem.


Solution

  • In your current code you have a code that can cause you errors since you should not access QML elements from C++, but vice versa, inject C++ objects to QML, in addition it has the fault that you will only get the start value and you will not be notified of the changes.

    In general if you want to monitor QML properties from C++ then you must create a QObject with a Q_PROPERTY of the same type of data you want to monitor, then export it with setContextProperty and make the connection in QML, then it is only a matter of monitoring the QProperty.

    main.cpp

    #include <QGuiApplication>
    #include <QIcon>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    
    #include <QDebug>
    
    class DialObserver: public QObject{
        Q_OBJECT
        Q_PROPERTY(int speed READ speed WRITE setSpeed NOTIFY speedChanged)
        int m_speed;
    public:
        using QObject::QObject;
        int speed() const{
            return m_speed;
        }
    public slots:
        void setSpeed(int speed){
            if (m_speed == speed)
                return;
            m_speed = speed;
            emit speedChanged(m_speed);
        }
    signals:
        void speedChanged(int speed);
    };
    
    int main(int argc, char *argv[])
    {
        QGuiApplication::setApplicationName("Automotive");
        QGuiApplication::setOrganizationName("QtProject");
        QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
    
        QGuiApplication app(argc, argv);
    
        QIcon::setThemeName("automotive");
    
        DialObserver dial_observer;
    
        QQmlApplicationEngine engine;
        engine.rootContext()->setContextProperty("dial_observer", &dial_observer);
        QObject::connect(&dial_observer, &DialObserver::speedChanged, [](int speed){
            qDebug() << speed;
        });
        engine.load(QUrl("qrc:/qml/automotive.qml"));
        if (engine.rootObjects().isEmpty())
            return -1;
        return app.exec();
    }
    
    #include "main.moc"
    

    automotive.qml

    // ...
    Dial {
        id: volumeDial
        onValueChanged: dial_observer.speed = value.toFixed(0)
        from: 0
        value: 42
        to: 100
        // ...