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?
QtWS25 Last Chance

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 last edited by topse
    #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

    raven-worxR 1 Reply Last reply
    0
    • T topse

      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

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on 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
      1
      • raven-worxR raven-worx

        @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 last edited by
        #3

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

        raven-worxR 1 Reply Last reply
        0
        • raven-worxR raven-worx

          @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 last edited by Tikani
          #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.

          raven-worxR 1 Reply Last reply
          0
          • T Tikani

            @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.

            raven-worxR Offline
            raven-worxR Offline
            raven-worx
            Moderators
            wrote on 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

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

              raven-worxR Offline
              raven-worxR Offline
              raven-worx
              Moderators
              wrote on 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
              0
              • raven-worxR raven-worx

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

                T Offline
                T Offline
                topse
                wrote on 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
                • raven-worxR raven-worx

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

                  T Offline
                  T Offline
                  topse
                  wrote on last edited by topse
                  #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

                  raven-worxR 1 Reply Last reply
                  0
                  • T topse

                    @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

                    raven-worxR Offline
                    raven-worxR Offline
                    raven-worx
                    Moderators
                    wrote on 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
                    0
                    • raven-worxR raven-worx

                      @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 last edited by topse
                      #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.

                      raven-worxR 1 Reply Last reply
                      0
                      • T topse

                        @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.

                        raven-worxR Offline
                        raven-worxR Offline
                        raven-worx
                        Moderators
                        wrote on last edited by raven-worx
                        #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
                        0
                        • raven-worxR raven-worx

                          @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 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

                          • Login

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