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. Signal not transported from QML to cpp?
Forum Update on Monday, May 27th 2025

Signal not transported from QML to cpp?

Scheduled Pinned Locked Moved Solved QML and Qt Quick
12 Posts 3 Posters 3.2k 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.
  • T Offline
    T Offline
    topse
    wrote on 10 Oct 2016, 12:22 last edited by topse 10 Oct 2016, 12:24
    #1

    Hi,
    I have a very strange behaviour. I have exposed a CPP-Object to QML and in QML I change the value of a QString-Property.
    On CPP-Side I am connected to the notify-signal for that property.

    Expected behaviour:
    CPP-Side gets notified for the value-change.

    Actual behaviour:
    CPP-Side is not being notified about value-change.

    Strange: In a small Test-Programm with CPP-Only it works.

    I found something in the "activate"-Function of QMetaObject which I dont understand:

    void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv)
    {
        int signal_index = signalOffset + local_signal_index;
    
        if (sender->d_func()->blockSig)
            return;
    
        if (sender->d_func()->isDeclarativeSignalConnected(signal_index)
                && QAbstractDeclarativeData::signalEmitted) {
            QAbstractDeclarativeData::signalEmitted(sender->d_func()->declarativeData, sender,
                                                    signal_index, argv);
        }
    
        if (!sender->d_func()->isSignalConnected(signal_index, /*checkDeclarative =*/ false)
            && !qt_signal_spy_callback_set.signal_begin_callback
            && !qt_signal_spy_callback_set.signal_end_callback) {
            // The possible declarative connection is done, and nothing else is connected, so:
            return;
        }
    

    The last if, see qobject.cpp line 3621, sorts out the notification. Means: we are leaving the activate-function with the last return in the above code snippet. Declarative Stuff seems to get notified, some lines before...

    Anyone has an idea, why cpp-signalling is skipped?

    Best Regards,
    Tobias

    R 1 Reply Last reply 10 Oct 2016, 13:12
    0
    • T topse
      10 Oct 2016, 12:22

      Hi,
      I have a very strange behaviour. I have exposed a CPP-Object to QML and in QML I change the value of a QString-Property.
      On CPP-Side I am connected to the notify-signal for that property.

      Expected behaviour:
      CPP-Side gets notified for the value-change.

      Actual behaviour:
      CPP-Side is not being notified about value-change.

      Strange: In a small Test-Programm with CPP-Only it works.

      I found something in the "activate"-Function of QMetaObject which I dont understand:

      void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv)
      {
          int signal_index = signalOffset + local_signal_index;
      
          if (sender->d_func()->blockSig)
              return;
      
          if (sender->d_func()->isDeclarativeSignalConnected(signal_index)
                  && QAbstractDeclarativeData::signalEmitted) {
              QAbstractDeclarativeData::signalEmitted(sender->d_func()->declarativeData, sender,
                                                      signal_index, argv);
          }
      
          if (!sender->d_func()->isSignalConnected(signal_index, /*checkDeclarative =*/ false)
              && !qt_signal_spy_callback_set.signal_begin_callback
              && !qt_signal_spy_callback_set.signal_end_callback) {
              // The possible declarative connection is done, and nothing else is connected, so:
              return;
          }
      

      The last if, see qobject.cpp line 3621, sorts out the notification. Means: we are leaving the activate-function with the last return in the above code snippet. Declarative Stuff seems to get notified, some lines before...

      Anyone has an idea, why cpp-signalling is skipped?

      Best Regards,
      Tobias

      R Offline
      R Offline
      raven-worx
      Moderators
      wrote on 10 Oct 2016, 13:12 last edited by
      #2

      @topse
      Just to make sure: Are you triggering the signal whenever the value changes? So simply specifying the NOTIFY signal isn't enough. That just tells the meta-object system what the corresponding signal is.

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      T T 2 Replies Last reply 10 Oct 2016, 14:05
      1
      • R raven-worx
        10 Oct 2016, 13:12

        @topse
        Just to make sure: Are you triggering the signal whenever the value changes? So simply specifying the NOTIFY signal isn't enough. That just tells the meta-object system what the corresponding signal is.

        T Offline
        T Offline
        topse
        wrote on 10 Oct 2016, 14:05 last edited by
        #3

        @raven-worx
        yeah... I know :-) When changing the value in the set-Function, the signal is called...

        R 1 Reply Last reply 10 Oct 2016, 16:56
        0
        • R raven-worx
          10 Oct 2016, 13:12

          @topse
          Just to make sure: Are you triggering the signal whenever the value changes? So simply specifying the NOTIFY signal isn't enough. That just tells the meta-object system what the corresponding signal is.

          T Offline
          T Offline
          Tikani
          wrote on 10 Oct 2016, 16:22 last edited by Tikani 10 Oct 2016, 16:24
          #4

          @raven-worx offtop - should I manually bind NOTIFY signal with some slot in QML file if I want continuous refreshing of displaying value whenever and wherever it changed? In my application I need to change some variable in a context object attached to main.qml and the result must be displayed immediately and (it's desirable) automatically after evaluation on the context object side without any hand work like it's done in classic Qt Widgets application by overriding event handlers.

          R 1 Reply Last reply 10 Oct 2016, 16:55
          0
          • T Tikani
            10 Oct 2016, 16:22

            @raven-worx offtop - should I manually bind NOTIFY signal with some slot in QML file if I want continuous refreshing of displaying value whenever and wherever it changed? In my application I need to change some variable in a context object attached to main.qml and the result must be displayed immediately and (it's desirable) automatically after evaluation on the context object side without any hand work like it's done in classic Qt Widgets application by overriding event handlers.

            R Offline
            R Offline
            raven-worx
            Moderators
            wrote on 10 Oct 2016, 16:55 last edited by
            #5

            @Tikani
            well the most effortless way is to use QML's property binding feature

            --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
            If you have a question please use the forum so others can benefit from the solution in the future

            1 Reply Last reply
            0
            • T topse
              10 Oct 2016, 14:05

              @raven-worx
              yeah... I know :-) When changing the value in the set-Function, the signal is called...

              R Offline
              R Offline
              raven-worx
              Moderators
              wrote on 10 Oct 2016, 16:56 last edited by
              #6

              @topse
              please show some more code, maybe there can be spotted more

              --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
              If you have a question please use the forum so others can benefit from the solution in the future

              T 2 Replies Last reply 11 Oct 2016, 09:17
              0
              • R raven-worx
                10 Oct 2016, 16:56

                @topse
                please show some more code, maybe there can be spotted more

                T Offline
                T Offline
                topse
                wrote on 11 Oct 2016, 09:17 last edited by
                #7

                @raven-worx
                To be honest, its a bit complicated to give more code... First there is a CPP-Type passed to QML and instantiated there, this type has a QObject which has the property... I will have a look, what I can do to get that in short...

                1 Reply Last reply
                0
                • R raven-worx
                  10 Oct 2016, 16:56

                  @topse
                  please show some more code, maybe there can be spotted more

                  T Offline
                  T Offline
                  topse
                  wrote on 11 Oct 2016, 09:59 last edited by topse 10 Nov 2016, 10:02
                  #8

                  @raven-worx

                  Hi Raven,
                  situation gets more complicated... I try it here:

                  In QML we have a view:

                  import QtQuick 2.7
                  import com.mycompany.qmlcomponents 1.0
                  
                  Page{
                  
                    A {
                      id: ctrl
                    }
                  
                    textFieldNachname {
                      onTextChanged: ctrl.card.nachname = text;
                    }
                  
                  
                    testButton {
                      onClicked: ctrl.testfct();
                    }
                  }
                  

                  Class A we have here:

                  class A: public QObject
                  {
                      Q_OBJECT
                      Q_PROPERTY(JCard* card READ card CONSTANT)
                    private:
                      JCard *_card;
                    public:
                      JCard *card() const;
                      
                      Q_INVOKABLE void testfct();
                    
                    private slots:
                      void slotTest();
                  }
                  
                  A::A(QObject *parent)
                    : QObject(parent)
                  {
                    _card = new JCard(this);
                  
                    bool success;
                    success = connect(_card, SIGNAL(nachnameChanged()), SLOT(slotTest()) ); Q_ASSERT(success);
                  }
                  
                  void A::testfct()
                  {
                    qDebug() << "testfct: " << _card->get_nachname();
                    _card->nachnameChanged();
                  }
                  
                  void A::slotTest()
                  {
                    qDebug() << "slotTest: Nachname changed to " << _card->get_nachname();
                  }
                  

                  And JCard:

                  class JCard : public QObject
                  {
                      Q_OBJECT
                      // Creates a property with setters and getters and notification
                      QML_WRITABLE_AUTO_PROPERTY(QString, nachname)
                  
                    public:
                     JCard(QObject *parent = Q_NULLPTR);
                  };
                  

                  Class A and JCard are given to QML:

                    qmlRegisterType<A>  ("com.mycompany.qmlcomponents", 1, 0, "A");
                    qmlRegisterType<JCard>("com.mycompany.qmlcomponents", 1, 0, "JCard");
                  

                  Expected Behaviour:
                  When I changed the text in textFieldNachname, it is given to the JCard-Object (this works -- in Debugger I see the internal data of JCard is OK!) and a notification is given to A::slotTest() (this does not work).

                  Test-Case 1:
                  I can trigger the A::testfct() with the testButton in QML. A::testfct() gives a debug-output which shows, that the internal data is OK. But even the manual signal triggering in A::testfct() here has no effect.

                  Test-Case 2:
                  Now I have changed A::testfct():

                  void A::testfct()
                  {
                    bool success = connect(_card, SIGNAL(nachnameChanged()), SLOT(slotTest()) ); Q_ASSERT(success);
                    qDebug() << "testfct: " << _card->get_nachname();
                    _card->nachnameChanged();
                  }
                  

                  As you can see I am doing the connection for the signal again. After that, the slotTest() gets notified correctly when I change the content of the textFieldNachname.

                  So now the question: Why does it not work to do the connection in the constructor? Do you have an idea? Should I make a ticket of this instance?

                  Best Regards,
                  Tobias

                  R 1 Reply Last reply 11 Oct 2016, 10:33
                  0
                  • T topse
                    11 Oct 2016, 09:59

                    @raven-worx

                    Hi Raven,
                    situation gets more complicated... I try it here:

                    In QML we have a view:

                    import QtQuick 2.7
                    import com.mycompany.qmlcomponents 1.0
                    
                    Page{
                    
                      A {
                        id: ctrl
                      }
                    
                      textFieldNachname {
                        onTextChanged: ctrl.card.nachname = text;
                      }
                    
                    
                      testButton {
                        onClicked: ctrl.testfct();
                      }
                    }
                    

                    Class A we have here:

                    class A: public QObject
                    {
                        Q_OBJECT
                        Q_PROPERTY(JCard* card READ card CONSTANT)
                      private:
                        JCard *_card;
                      public:
                        JCard *card() const;
                        
                        Q_INVOKABLE void testfct();
                      
                      private slots:
                        void slotTest();
                    }
                    
                    A::A(QObject *parent)
                      : QObject(parent)
                    {
                      _card = new JCard(this);
                    
                      bool success;
                      success = connect(_card, SIGNAL(nachnameChanged()), SLOT(slotTest()) ); Q_ASSERT(success);
                    }
                    
                    void A::testfct()
                    {
                      qDebug() << "testfct: " << _card->get_nachname();
                      _card->nachnameChanged();
                    }
                    
                    void A::slotTest()
                    {
                      qDebug() << "slotTest: Nachname changed to " << _card->get_nachname();
                    }
                    

                    And JCard:

                    class JCard : public QObject
                    {
                        Q_OBJECT
                        // Creates a property with setters and getters and notification
                        QML_WRITABLE_AUTO_PROPERTY(QString, nachname)
                    
                      public:
                       JCard(QObject *parent = Q_NULLPTR);
                    };
                    

                    Class A and JCard are given to QML:

                      qmlRegisterType<A>  ("com.mycompany.qmlcomponents", 1, 0, "A");
                      qmlRegisterType<JCard>("com.mycompany.qmlcomponents", 1, 0, "JCard");
                    

                    Expected Behaviour:
                    When I changed the text in textFieldNachname, it is given to the JCard-Object (this works -- in Debugger I see the internal data of JCard is OK!) and a notification is given to A::slotTest() (this does not work).

                    Test-Case 1:
                    I can trigger the A::testfct() with the testButton in QML. A::testfct() gives a debug-output which shows, that the internal data is OK. But even the manual signal triggering in A::testfct() here has no effect.

                    Test-Case 2:
                    Now I have changed A::testfct():

                    void A::testfct()
                    {
                      bool success = connect(_card, SIGNAL(nachnameChanged()), SLOT(slotTest()) ); Q_ASSERT(success);
                      qDebug() << "testfct: " << _card->get_nachname();
                      _card->nachnameChanged();
                    }
                    

                    As you can see I am doing the connection for the signal again. After that, the slotTest() gets notified correctly when I change the content of the textFieldNachname.

                    So now the question: Why does it not work to do the connection in the constructor? Do you have an idea? Should I make a ticket of this instance?

                    Best Regards,
                    Tobias

                    R Offline
                    R Offline
                    raven-worx
                    Moderators
                    wrote on 11 Oct 2016, 10:33 last edited by
                    #9

                    @topse
                    Are there any warnings in the console?

                    Does this output on the console?

                    textFieldNachname {
                        onTextChanged: {
                                console.log("textChanged:" + text );
                                ctrl.card.nachname = text;
                           }
                      }
                    

                    Alternatively you can use QML property binding directly:

                    Page{
                      textFieldNachname {
                        id: nachnameInput
                        onTextChanged: ctrl.card.nachname = text;
                      }
                    
                      A {
                        id: ctrl
                    
                        Component.onCompleted: {
                                source = Qt.binding(function() {
                                           card.nachname = nachnameInput.text
                                    }
                                );
                          }
                      }
                    

                    --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                    If you have a question please use the forum so others can benefit from the solution in the future

                    T 1 Reply Last reply 11 Oct 2016, 14:05
                    0
                    • R raven-worx
                      11 Oct 2016, 10:33

                      @topse
                      Are there any warnings in the console?

                      Does this output on the console?

                      textFieldNachname {
                          onTextChanged: {
                                  console.log("textChanged:" + text );
                                  ctrl.card.nachname = text;
                             }
                        }
                      

                      Alternatively you can use QML property binding directly:

                      Page{
                        textFieldNachname {
                          id: nachnameInput
                          onTextChanged: ctrl.card.nachname = text;
                        }
                      
                        A {
                          id: ctrl
                      
                          Component.onCompleted: {
                                  source = Qt.binding(function() {
                                             card.nachname = nachnameInput.text
                                      }
                                  );
                            }
                        }
                      
                      T Offline
                      T Offline
                      topse
                      wrote on 11 Oct 2016, 14:05 last edited by topse 10 Nov 2016, 14:06
                      #10

                      @raven-worx
                      There are no warnings and it gives output. Thanks for the advice -- seems to be a bit nicer from reading point of view.

                      R 1 Reply Last reply 11 Oct 2016, 14:08
                      0
                      • T topse
                        11 Oct 2016, 14:05

                        @raven-worx
                        There are no warnings and it gives output. Thanks for the advice -- seems to be a bit nicer from reading point of view.

                        R Offline
                        R Offline
                        raven-worx
                        Moderators
                        wrote on 11 Oct 2016, 14:08 last edited by raven-worx 10 Nov 2016, 14:09
                        #11

                        @topse
                        then the only thing left i can think of is that the JCard instance you connect in the constructor gets deleted/replaced?
                        But to make sure, you can move the connect() statement into the constructor of JCard, since you also pass an instance of A to the constructor.

                        --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                        If you have a question please use the forum so others can benefit from the solution in the future

                        T 1 Reply Last reply 11 Oct 2016, 14:16
                        0
                        • R raven-worx
                          11 Oct 2016, 14:08

                          @topse
                          then the only thing left i can think of is that the JCard instance you connect in the constructor gets deleted/replaced?
                          But to make sure, you can move the connect() statement into the constructor of JCard, since you also pass an instance of A to the constructor.

                          T Offline
                          T Offline
                          topse
                          wrote on 11 Oct 2016, 14:16 last edited by
                          #12

                          @raven-worx
                          :-( What an i***t I am... setting a breakpoint in the destructor... should have done that before... and should not happen... Thanks for giving me a talk :-)

                          Best Regards,
                          Tobias

                          1 Reply Last reply
                          0

                          1/12

                          10 Oct 2016, 12:22

                          • Login

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