Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. creating QML signals for C++ slots

creating QML signals for C++ slots

Scheduled Pinned Locked Moved Solved QML and Qt Quick
29 Posts 7 Posters 4.3k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by
    #1

    Hi all -

    I've looked over this page, which has some good information on the topic. It uses, however, a QQuickView object:

     QQuickView view(QUrl::fromLocalFile("MyItem.qml"));
        QObject *item = view.rootObject();
    
        MyClass myClass;
        QObject::connect(item, SIGNAL(qmlSignal(QString)),
                         &myClass, SLOT(cppSlot(QString)));
    

    Whereas my main.cpp (created by the wizard) uses a QQmlApplicationEngine:

        QQmlApplicationEngine engine;
        engine.load(url);
    

    So, what's the equivalent to:

    QQuickView view(QUrl::fromLocalFile("MyItem.qml"));
        QObject *item = view.rootObject();
    

    For QQmlApplicationEngine? Or, backing up a bit, how best to connect QML signals to C++ slots in this case?

    Thanks...

    JKSHJ 1 Reply Last reply
    0
    • mzimmersM mzimmers

      Hi all -

      I've looked over this page, which has some good information on the topic. It uses, however, a QQuickView object:

       QQuickView view(QUrl::fromLocalFile("MyItem.qml"));
          QObject *item = view.rootObject();
      
          MyClass myClass;
          QObject::connect(item, SIGNAL(qmlSignal(QString)),
                           &myClass, SLOT(cppSlot(QString)));
      

      Whereas my main.cpp (created by the wizard) uses a QQmlApplicationEngine:

          QQmlApplicationEngine engine;
          engine.load(url);
      

      So, what's the equivalent to:

      QQuickView view(QUrl::fromLocalFile("MyItem.qml"));
          QObject *item = view.rootObject();
      

      For QQmlApplicationEngine? Or, backing up a bit, how best to connect QML signals to C++ slots in this case?

      Thanks...

      JKSHJ Offline
      JKSHJ Offline
      JKSH
      Moderators
      wrote on last edited by
      #2

      @mzimmers said in creating QML signals for C++ slots:

      So, what's the equivalent to:

      QQuickView view(QUrl::fromLocalFile("MyItem.qml"));
          QObject *item = view.rootObject();
      

      For QQmlApplicationEngine?

      https://doc.qt.io/qt-6/qqmlapplicationengine.html#rootObjects You can usually just take the first object.

      Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

      mzimmersM GrecKoG 2 Replies Last reply
      2
      • JKSHJ JKSH

        @mzimmers said in creating QML signals for C++ slots:

        So, what's the equivalent to:

        QQuickView view(QUrl::fromLocalFile("MyItem.qml"));
            QObject *item = view.rootObject();
        

        For QQmlApplicationEngine?

        https://doc.qt.io/qt-6/qqmlapplicationengine.html#rootObjects You can usually just take the first object.

        mzimmersM Offline
        mzimmersM Offline
        mzimmers
        wrote on last edited by
        #3

        @JKSH thanks for the reply. What I'm trying to do is get the QML to report the change of a slider (this is a custom slider, not the QML Slider object) value to a C++ object via a signal. The author of the custom slider uses a MouseArea to contain the handle. My thought was to use a MouseArea.released() signal. But since this custom slider's handle is buried in a few levels of QML files, how do I make it "known" to the C++ code?

        A better question might be, is this the best way to go about this, or is there a more straightforward mechanism for capturing the custom slider movement?

        Thanks...

        1 Reply Last reply
        0
        • JKSHJ JKSH

          @mzimmers said in creating QML signals for C++ slots:

          So, what's the equivalent to:

          QQuickView view(QUrl::fromLocalFile("MyItem.qml"));
              QObject *item = view.rootObject();
          

          For QQmlApplicationEngine?

          https://doc.qt.io/qt-6/qqmlapplicationengine.html#rootObjects You can usually just take the first object.

          GrecKoG Offline
          GrecKoG Offline
          GrecKo
          Qt Champions 2018
          wrote on last edited by GrecKo
          #4

          @JKSH said in creating QML signals for C++ slots:

          https://doc.qt.io/qt-6/qqmlapplicationengine.html#rootObjects You can usually just take the first object.

          Don't do that. https://www.youtube.com/watch?v=vzs5VPTf4QQ&t=1400s

          @mzimmers What you want is exposing a C++ property and bind to it/set it in QML.
          It would be easier with a Qt Quick Controls 2 Slider as for the property bindings, you can customize its look anyway.

          // in  your C++ class:
          Q_PROPERTY(float value READ value WRITE setValue NOTIFY valueChanged)
          // ...
          
          // in your QML file:
          Slider {
              from: 0
              to: 100
              value: CppObject.value
              onMoved: CppObject.value = value
          }
          mzimmersM SGaistS 2 Replies Last reply
          2
          • GrecKoG GrecKo

            @JKSH said in creating QML signals for C++ slots:

            https://doc.qt.io/qt-6/qqmlapplicationengine.html#rootObjects You can usually just take the first object.

            Don't do that. https://www.youtube.com/watch?v=vzs5VPTf4QQ&t=1400s

            @mzimmers What you want is exposing a C++ property and bind to it/set it in QML.
            It would be easier with a Qt Quick Controls 2 Slider as for the property bindings, you can customize its look anyway.

            // in  your C++ class:
            Q_PROPERTY(float value READ value WRITE setValue NOTIFY valueChanged)
            // ...
            
            // in your QML file:
            Slider {
                from: 0
                to: 100
                value: CppObject.value
                onMoved: CppObject.value = value
            }
            mzimmersM Offline
            mzimmersM Offline
            mzimmers
            wrote on last edited by
            #5

            @GrecKo I can see how your example will update the value in the C++ code, but I don't see how the C++ code is notified that the change has been made. Wouldn't a signal from QML be more straightforward (if I can figure out how to do it)?

            fcarneyF 1 Reply Last reply
            0
            • mzimmersM mzimmers

              @GrecKo I can see how your example will update the value in the C++ code, but I don't see how the C++ code is notified that the change has been made. Wouldn't a signal from QML be more straightforward (if I can figure out how to do it)?

              fcarneyF Offline
              fcarneyF Offline
              fcarney
              wrote on last edited by
              #6

              @mzimmers said in creating QML signals for C++ slots:

              Wouldn't a signal from QML be more straightforward (if I can figure out how to do it)?

              valueChanged is the signal that gets fired when the value changes. You can connect to that signal in the C++ object.

              C++ is a perfectly valid school of magic.

              mzimmersM 1 Reply Last reply
              1
              • fcarneyF fcarney

                @mzimmers said in creating QML signals for C++ slots:

                Wouldn't a signal from QML be more straightforward (if I can figure out how to do it)?

                valueChanged is the signal that gets fired when the value changes. You can connect to that signal in the C++ object.

                mzimmersM Offline
                mzimmersM Offline
                mzimmers
                wrote on last edited by mzimmers
                #7

                @fcarney said in creating QML signals for C++ slots:

                valueChanged is the signal that gets fired when the value changes. You can connect to that signal in the C++ object.

                I thought that valueChanged was the signal in the C++ object?

                fcarneyF 1 Reply Last reply
                0
                • GrecKoG GrecKo

                  @JKSH said in creating QML signals for C++ slots:

                  https://doc.qt.io/qt-6/qqmlapplicationengine.html#rootObjects You can usually just take the first object.

                  Don't do that. https://www.youtube.com/watch?v=vzs5VPTf4QQ&t=1400s

                  @mzimmers What you want is exposing a C++ property and bind to it/set it in QML.
                  It would be easier with a Qt Quick Controls 2 Slider as for the property bindings, you can customize its look anyway.

                  // in  your C++ class:
                  Q_PROPERTY(float value READ value WRITE setValue NOTIFY valueChanged)
                  // ...
                  
                  // in your QML file:
                  Slider {
                      from: 0
                      to: 100
                      value: CppObject.value
                      onMoved: CppObject.value = value
                  }
                  SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by SGaist
                  #8

                  Hi

                  @GrecKo said in creating QML signals for C++ slots:

                  // in  your C++ class:
                  Q_PROPERTY(float value READ value WRITE setValue NOTIFY valueChanged)
                  // ...
                  
                  // in your QML file:
                  Slider {
                      from: 0
                      to: 100
                      value: CppObject.value
                      onMoved: CppObject.value = value
                  }
                  

                  The value property of the Slider object is linked to the value property of your C++ object hence if you fire the valueChanged signal from your C++ object, the Slider object will get the notification and update its value.

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  mzimmersM 1 Reply Last reply
                  2
                  • mzimmersM mzimmers

                    @fcarney said in creating QML signals for C++ slots:

                    valueChanged is the signal that gets fired when the value changes. You can connect to that signal in the C++ object.

                    I thought that valueChanged was the signal in the C++ object?

                    fcarneyF Offline
                    fcarneyF Offline
                    fcarney
                    wrote on last edited by
                    #9

                    @mzimmers said in creating QML signals for C++ slots:

                    I thought that valueChanged was the signal in the C++ object?

                    It is, and it should fire when the WRITE method (setValue) is called on value. So you can use that signal with other objects on the C++ side to notify of the update.

                    C++ is a perfectly valid school of magic.

                    SGaistS 1 Reply Last reply
                    1
                    • fcarneyF fcarney

                      @mzimmers said in creating QML signals for C++ slots:

                      I thought that valueChanged was the signal in the C++ object?

                      It is, and it should fire when the WRITE method (setValue) is called on value. So you can use that signal with other objects on the C++ side to notify of the update.

                      SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      @fcarney said in creating QML signals for C++ slots:

                      @mzimmers said in creating QML signals for C++ slots:

                      I thought that valueChanged was the signal in the C++ object?

                      It is, and it should fire when the WRITE method (setValue) is called on value. So you can use that signal with other objects on the C++ side to notify of the update.

                      One small addition, even if it sounds obvious, don't forget to emit the signal only when there's an actual value change otherwise you will have a signal storm which is not what you want.

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      2
                      • SGaistS SGaist

                        Hi

                        @GrecKo said in creating QML signals for C++ slots:

                        // in  your C++ class:
                        Q_PROPERTY(float value READ value WRITE setValue NOTIFY valueChanged)
                        // ...
                        
                        // in your QML file:
                        Slider {
                            from: 0
                            to: 100
                            value: CppObject.value
                            onMoved: CppObject.value = value
                        }
                        

                        The value property of the Slider object is linked to the value property of your C++ object hence if you fire the valueChanged signal from your C++ object, the Slider object will get the notification and update its value.

                        mzimmersM Offline
                        mzimmersM Offline
                        mzimmers
                        wrote on last edited by
                        #11

                        @SGaist said in creating QML signals for C++ slots:

                        The value property of the Slider object is linked to the value property of your C++ object hence if you fire the valueChanged signal from your C++ object, the Slider object will get the notification and update its value.

                        I can see that I'm doing a bad job of explaining what I'm trying to do: I want the UI to signal the app when the user manipulates the slider. Seems I need to link a signal from the QML to a slot in my C++ object.

                        Or...am I totally blowing this sideways?

                        1 Reply Last reply
                        0
                        • fcarneyF Offline
                          fcarneyF Offline
                          fcarney
                          wrote on last edited by
                          #12

                          @SGaist said in creating QML signals for C++ slots:

                          // in your C++ class:
                          Q_PROPERTY(float value READ value WRITE setValue NOTIFY valueChanged)
                          // ...

                          // in your QML file:
                          Slider {
                          from: 0
                          to: 100
                          value: CppObject.value
                          onMoved: CppObject.value = value // this calls the "setValue" function of the property
                          }

                          The CppObject shown in the qml here defines a property called "value". This would be a context property or similar method of exposing a cpp object. Will be lower case on first letter as upper case context properties are not allowed. So we will now refer to it as "cppObject".

                          The "value" property has a signal that is fired when it changes. This is called "valueChanged". The method that calls that signal is called "setValue".

                          So this function might look like this:

                          void CppObject::setValue(float val){
                              if(val == m_value) // use float fuzzy compare here
                                  return;
                              m_value = val;
                              emit valueChanged(m_value);
                          }
                          

                          Somewhere in your cpp:
                          CppObject cppobject; // this object gets exposed as context property.

                          connect(&cppobject, &CppObject::valueChanged, [](float value){
                          // so something with value
                          });

                          C++ is a perfectly valid school of magic.

                          1 Reply Last reply
                          1
                          • mzimmersM Offline
                            mzimmersM Offline
                            mzimmers
                            wrote on last edited by
                            #13

                            I seem to still be missing a piece here. Various snippets:

                            main.cpp

                                SliderReporter sp;
                                QGuiApplication app(argc, argv);
                                QQmlApplicationEngine engine;
                                engine.rootContext()->setContextProperty("sp", &sp);
                                engine.load(url);
                            

                            sliderreporter.h

                            class SliderReporter : public QObject
                            {
                                Q_OBJECT
                                Q_PROPERTY(float m_value MEMBER m_value READ value WRITE setValue NOTIFY valueChanged)
                            
                            public:
                                explicit SliderReporter(QObject *parent = nullptr);
                                float value() { return m_value; }
                                void setValue (float value) { m_value = value; }
                            public slots:
                                void reportValue(int i) {
                                    qDebug() << "new value of slider is:" << i;
                                }
                            signals:
                                void valueChanged(float value);
                            private:
                                float m_value;
                            };
                            

                            sliderreporter.cpp:

                            SliderReporter::SliderReporter(QObject *parent)
                                : QObject{parent}
                            {
                                QMetaObject::Connection c;
                                bool b;
                            
                                c = QObject::connect(this, &SliderReporter::valueChanged, this, &SliderReporter::reportValue);
                                b = static_cast<bool>(c);
                                qDebug() << b;
                            }
                            

                            and deep in my QLM code:

                            MouseArea {
                            	onReleased: sp.value = value
                            

                            So, I'm performing the following (I think):

                            1. setting the context property in main.cpp
                            2. establishing the supporting methods to the property in sliderreporter.h
                            3. creating a way to "see" the signal in my SliderReporter c'tor
                            4. referencing my "sp" in my QML

                            What am I leaving out?

                            Thanks...

                            J.HilkJ 1 Reply Last reply
                            0
                            • mzimmersM mzimmers

                              I seem to still be missing a piece here. Various snippets:

                              main.cpp

                                  SliderReporter sp;
                                  QGuiApplication app(argc, argv);
                                  QQmlApplicationEngine engine;
                                  engine.rootContext()->setContextProperty("sp", &sp);
                                  engine.load(url);
                              

                              sliderreporter.h

                              class SliderReporter : public QObject
                              {
                                  Q_OBJECT
                                  Q_PROPERTY(float m_value MEMBER m_value READ value WRITE setValue NOTIFY valueChanged)
                              
                              public:
                                  explicit SliderReporter(QObject *parent = nullptr);
                                  float value() { return m_value; }
                                  void setValue (float value) { m_value = value; }
                              public slots:
                                  void reportValue(int i) {
                                      qDebug() << "new value of slider is:" << i;
                                  }
                              signals:
                                  void valueChanged(float value);
                              private:
                                  float m_value;
                              };
                              

                              sliderreporter.cpp:

                              SliderReporter::SliderReporter(QObject *parent)
                                  : QObject{parent}
                              {
                                  QMetaObject::Connection c;
                                  bool b;
                              
                                  c = QObject::connect(this, &SliderReporter::valueChanged, this, &SliderReporter::reportValue);
                                  b = static_cast<bool>(c);
                                  qDebug() << b;
                              }
                              

                              and deep in my QLM code:

                              MouseArea {
                              	onReleased: sp.value = value
                              

                              So, I'm performing the following (I think):

                              1. setting the context property in main.cpp
                              2. establishing the supporting methods to the property in sliderreporter.h
                              3. creating a way to "see" the signal in my SliderReporter c'tor
                              4. referencing my "sp" in my QML

                              What am I leaving out?

                              Thanks...

                              J.HilkJ Online
                              J.HilkJ Online
                              J.Hilk
                              Moderators
                              wrote on last edited by
                              #14

                              @mzimmers

                              //sliderreporter.h
                              #ifndef SLIDERREPORTER_H
                              #define SLIDERREPORTER_H
                              
                              #include <QObject>
                              #include <QDebug>
                              
                              class SliderReporter : public QObject
                              {
                                  Q_OBJECT
                                  Q_PROPERTY(float value READ value WRITE setValue NOTIFY valueChanged)
                              
                              public:
                                  explicit SliderReporter(QObject *parent = nullptr)
                                      : QObject{parent}
                                  {
                                      connect(this, &SliderReporter::valueChanged, this, &SliderReporter::onValueChanged);
                                  }
                              
                                  [[nodiscard]] float value() const noexcept { return m_value; }
                                  void setValue(float newValue)
                                  {
                                      if (qFuzzyCompare(m_value , newValue))
                                          return;
                                      m_value = newValue;
                                      emit valueChanged(m_value);
                                  }
                              
                              public slots:
                                  void setValueViaDirectCall(float value) {setValue(value);}
                                  /*Q_INVOKABLE <- could be added for readability, but not needed, since it is a public slot*/
                                  //Q_INVOKABLE void setValueViaDirectCall(float value) {setValue(value);}
                              
                                  void onValueChanged(float newValue){
                                      qDebug() << Q_FUNC_INFO << newValue << "-:-" << value();
                                  }
                              signals:
                                  void valueChanged(const float &value);
                              
                              private:
                                  float m_value;
                              };
                              
                              #endif // SLIDERREPORTER_H
                              
                              
                              //main.cpp
                              #include "sliderreporter.h"
                              
                              int main(int argc, char *argv[])
                              {
                                  QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
                                  SliderReporter sRep;
                                  QGuiApplication app(argc, argv);
                                  QQmlApplicationEngine engine;
                              
                                  engine.rootContext()->setContextProperty("sRep", &sRep);
                              
                                  const QUrl url(QStringLiteral("qrc:/main.qml"));
                                  engine.load(url);
                              
                              
                              
                                  return app.exec();
                              }
                              
                              //main.qml
                              import QtQuick 2.15
                              import QtQuick.Controls 2.15
                              import QtQuick.Window 2.15
                              import QtQuick.Layouts 1.15
                              
                              Window {
                                  id: root
                                  width: 800
                                  height: 600
                                  visible: true
                              
                                  Slider {
                                      from: 0
                                      to: 100
                                      value: sRep.value
                                      onMoved: sRep.value = value // calls setValue in your cpp file when slider handle is moved
                                  }
                              
                                  Timer{
                                      running:true
                                      repeat: true
                                      interval: 5000
                                      onTriggered: sRep.setValueViaDirectCall(20);
                                  }
                              }
                              

                              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                              Q: What's that?
                              A: It's blue light.
                              Q: What does it do?
                              A: It turns blue.

                              GrecKoG 1 Reply Last reply
                              3
                              • J.HilkJ J.Hilk

                                @mzimmers

                                //sliderreporter.h
                                #ifndef SLIDERREPORTER_H
                                #define SLIDERREPORTER_H
                                
                                #include <QObject>
                                #include <QDebug>
                                
                                class SliderReporter : public QObject
                                {
                                    Q_OBJECT
                                    Q_PROPERTY(float value READ value WRITE setValue NOTIFY valueChanged)
                                
                                public:
                                    explicit SliderReporter(QObject *parent = nullptr)
                                        : QObject{parent}
                                    {
                                        connect(this, &SliderReporter::valueChanged, this, &SliderReporter::onValueChanged);
                                    }
                                
                                    [[nodiscard]] float value() const noexcept { return m_value; }
                                    void setValue(float newValue)
                                    {
                                        if (qFuzzyCompare(m_value , newValue))
                                            return;
                                        m_value = newValue;
                                        emit valueChanged(m_value);
                                    }
                                
                                public slots:
                                    void setValueViaDirectCall(float value) {setValue(value);}
                                    /*Q_INVOKABLE <- could be added for readability, but not needed, since it is a public slot*/
                                    //Q_INVOKABLE void setValueViaDirectCall(float value) {setValue(value);}
                                
                                    void onValueChanged(float newValue){
                                        qDebug() << Q_FUNC_INFO << newValue << "-:-" << value();
                                    }
                                signals:
                                    void valueChanged(const float &value);
                                
                                private:
                                    float m_value;
                                };
                                
                                #endif // SLIDERREPORTER_H
                                
                                
                                //main.cpp
                                #include "sliderreporter.h"
                                
                                int main(int argc, char *argv[])
                                {
                                    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
                                    SliderReporter sRep;
                                    QGuiApplication app(argc, argv);
                                    QQmlApplicationEngine engine;
                                
                                    engine.rootContext()->setContextProperty("sRep", &sRep);
                                
                                    const QUrl url(QStringLiteral("qrc:/main.qml"));
                                    engine.load(url);
                                
                                
                                
                                    return app.exec();
                                }
                                
                                //main.qml
                                import QtQuick 2.15
                                import QtQuick.Controls 2.15
                                import QtQuick.Window 2.15
                                import QtQuick.Layouts 1.15
                                
                                Window {
                                    id: root
                                    width: 800
                                    height: 600
                                    visible: true
                                
                                    Slider {
                                        from: 0
                                        to: 100
                                        value: sRep.value
                                        onMoved: sRep.value = value // calls setValue in your cpp file when slider handle is moved
                                    }
                                
                                    Timer{
                                        running:true
                                        repeat: true
                                        interval: 5000
                                        onTriggered: sRep.setValueViaDirectCall(20);
                                    }
                                }
                                
                                GrecKoG Offline
                                GrecKoG Offline
                                GrecKo
                                Qt Champions 2018
                                wrote on last edited by GrecKo
                                #15

                                @J-Hilk
                                The same without the two unnecessary slots.

                                connect(this, *, this, *); is kind of a non sense most of the time. Signals and slots make sense when when you don't know where the signal will be connected. To notify a change of state to the outside. Here you can just call onValueChanged internally in the setValue (wheter there's a need to keep the two separated is left as en exercise to the reader).
                                Moreover exposing onValueChanged as a public slots pollutes the interface, why would you want to let the QML call it? Defining a function as slot is also not needed for the pointer to member function connect syntax. You can connect to a simple private member function (not that you should do it here).

                                What's the point with setValueViaDirectCall? you can do the same with property and not add additional complexity, keeping the property syntax :

                                onTriggered: sRep.value = 20

                                Sorry for being negative but we don't have to make QML integration more complicated than it is and less declarative than it should be (:

                                J.HilkJ 1 Reply Last reply
                                2
                                • GrecKoG GrecKo

                                  @J-Hilk
                                  The same without the two unnecessary slots.

                                  connect(this, *, this, *); is kind of a non sense most of the time. Signals and slots make sense when when you don't know where the signal will be connected. To notify a change of state to the outside. Here you can just call onValueChanged internally in the setValue (wheter there's a need to keep the two separated is left as en exercise to the reader).
                                  Moreover exposing onValueChanged as a public slots pollutes the interface, why would you want to let the QML call it? Defining a function as slot is also not needed for the pointer to member function connect syntax. You can connect to a simple private member function (not that you should do it here).

                                  What's the point with setValueViaDirectCall? you can do the same with property and not add additional complexity, keeping the property syntax :

                                  onTriggered: sRep.value = 20

                                  Sorry for being negative but we don't have to make QML integration more complicated than it is and less declarative than it should be (:

                                  J.HilkJ Online
                                  J.HilkJ Online
                                  J.Hilk
                                  Moderators
                                  wrote on last edited by
                                  #16

                                  @GrecKo ?

                                  I'm not suppling production code, but a simple example that shows the different ways one can achieve the OP's desired outcome.

                                  connect(this, *, this, *); is kind of a non sense most of the time. Signals and slots make sense when when you don't know where the signal will be connected. To notify a change of state to the outside. Here you can just call onValueChanged internally in the setValue (wheter there's a need to keep the two separated is left as en exercise to the reader).

                                  I whole hardly disagree, Property setters should do nothing but set a property and emit a signal. The c++ reaction to that changed signal can than be done in slot, that can, but doesn't have to be in the same class.

                                  I for example usually have one base class that contains all Properties, and one derived one, that contains the logic.

                                  Moreover exposing onValueChanged as a public slots pollutes the interface, why would you want to let the QML call it?

                                  I was to lazy to add the additional private, my bad.

                                  Defining a function as slot is also not needed for the pointer to member function connect syntax.

                                  I'm aware, but it (the intend) is still more readable, imho

                                  What's the point with setValueViaDirectCall? you can do the same with property and not add additional complexity, keeping the property syntax :

                                  onTriggered: sRep.value = 20

                                  again, showing an alternative.


                                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                                  Q: What's that?
                                  A: It's blue light.
                                  Q: What does it do?
                                  A: It turns blue.

                                  1 Reply Last reply
                                  1
                                  • mzimmersM Offline
                                    mzimmersM Offline
                                    mzimmers
                                    wrote on last edited by
                                    #17

                                    Thanks for the replies, guys. I had to re-read the docs a few times to really understand what I was missing - it was an explicit call to emit() in my setValue() function. It now works more or less as I hoped.

                                    A few wrap-up questions, please:

                                    1. if I do have to explicitly emit my setValue(), what is the purpose of its mention in the Q_PROPERTY macro?
                                    2. if I wanted to emit the signal from QML, can I change my QML statement:
                                    MouseArea {
                                        id: trackMouse
                                        onReleased: sp.value = control.value
                                    }
                                    

                                    to something more like:

                                    MouseArea {
                                        id: trackMouse
                                        onReleased {
                                            sp.value = control.value
                                            emit sp.valueChanged
                                        }
                                    }
                                    

                                    What's the correct syntax to do something like this? And, is it even a good idea to emit the signal from QML, or should I go ahead and do it per @J-Hilk's example?
                                    3. The above passage is the only modification I have to make to a third-party module. It would be nice to keep this module unmodified. Is there any way I can give trackMouse this property from outside the module?

                                    Thank you...

                                    B 1 Reply Last reply
                                    0
                                    • mzimmersM mzimmers

                                      Thanks for the replies, guys. I had to re-read the docs a few times to really understand what I was missing - it was an explicit call to emit() in my setValue() function. It now works more or less as I hoped.

                                      A few wrap-up questions, please:

                                      1. if I do have to explicitly emit my setValue(), what is the purpose of its mention in the Q_PROPERTY macro?
                                      2. if I wanted to emit the signal from QML, can I change my QML statement:
                                      MouseArea {
                                          id: trackMouse
                                          onReleased: sp.value = control.value
                                      }
                                      

                                      to something more like:

                                      MouseArea {
                                          id: trackMouse
                                          onReleased {
                                              sp.value = control.value
                                              emit sp.valueChanged
                                          }
                                      }
                                      

                                      What's the correct syntax to do something like this? And, is it even a good idea to emit the signal from QML, or should I go ahead and do it per @J-Hilk's example?
                                      3. The above passage is the only modification I have to make to a third-party module. It would be nice to keep this module unmodified. Is there any way I can give trackMouse this property from outside the module?

                                      Thank you...

                                      B Offline
                                      B Offline
                                      Bob64
                                      wrote on last edited by Bob64
                                      #18

                                      @mzimmers "if I do have to explicitly emit my setValue(), what is the purpose of its mention in the Q_PROPERTY macro?"

                                      The Q_PROPERTY macro is what gathers together the bits of your class interface that contribute to that property's implementation. Yes, you have to do the work to emit the signal so that there is a notification being generated, but unless you declare it in the macro, there is nothing to tell Qt that this particular signal is the one associated with that property change. Although regular naming conventions are usually used, Qt itself does not infer anything from the name. You could call the signal whatever you want.

                                      mzimmersM 1 Reply Last reply
                                      1
                                      • B Bob64

                                        @mzimmers "if I do have to explicitly emit my setValue(), what is the purpose of its mention in the Q_PROPERTY macro?"

                                        The Q_PROPERTY macro is what gathers together the bits of your class interface that contribute to that property's implementation. Yes, you have to do the work to emit the signal so that there is a notification being generated, but unless you declare it in the macro, there is nothing to tell Qt that this particular signal is the one associated with that property change. Although regular naming conventions are usually used, Qt itself does not infer anything from the name. You could call the signal whatever you want.

                                        mzimmersM Offline
                                        mzimmersM Offline
                                        mzimmers
                                        wrote on last edited by
                                        #19

                                        @Bob64 I'm not sure I fully understand your answer - to me, it sounds like including NOTIFY is merely bookkeeping. How (if at all) does it change the behavior of the program?

                                        Thanks...

                                        1 Reply Last reply
                                        0
                                        • fcarneyF Offline
                                          fcarneyF Offline
                                          fcarney
                                          wrote on last edited by
                                          #20

                                          @mzimmers said in creating QML signals for C++ slots:

                                          How (if at all) does it change the behavior of the program?

                                          It is how everything in QML gets notified when a value changes. So if you did the following:

                                          Text {
                                            text: sp.value
                                          }
                                          

                                          If the signal is not in the property definition "text" will never get updated. Every binding to every property in QML works this way.

                                          C++ is a perfectly valid school of magic.

                                          mzimmersM 1 Reply Last reply
                                          2

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved