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. Why is this a binding loop?
Forum Updated to NodeBB v4.3 + New Features

Why is this a binding loop?

Scheduled Pinned Locked Moved Solved QML and Qt Quick
14 Posts 4 Posters 2.3k Views 2 Watching
  • 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.
  • oria66O Offline
    oria66O Offline
    oria66
    wrote on last edited by oria66
    #2

    Hi, @mzimmers. Mmmm, question... why do you use a signal emission on a getter? I think it is unnecessary. I mean, Why do you want to inform to qml side of a change, if there is not? Unless your PosterModalChecklist() function modify your model... Is this your case?

    The truth is out there

    1 Reply Last reply
    1
    • mzimmersM mzimmers

      Hi all -

      I have a class with the following in it:

      Q_PROPERTY( QStringList posterModalChecklist
      	MEMBER m_posterModalChecklist
      	READ GetPosterModalChecklist
              NOTIFY EventPosterModalChecklistChangedForQML )
      			
      QStringList m_posterModalChecklist;
      void EventPosterModalChecklistChangedForQML(QStringList qsl);
        
      QStringList ChangeConsumables::GetPosterModalChecklist() {
        m_posterModalChecklist = m_batch[m_index]->PosterModalChecklist();
        emit EventPosterModalChecklistChangedForQML(m_posterModalChecklist);
        return m_posterModalChecklist;
      }
      

      Used in this QML:

      Column {
        Repeater {
      	model: changeConsumablesViewModel.posterModalChecklist
      	RowLayout {
      	  Label {
      		text: modelData
      

      At runtime I get an error about a binding loop on "model." The error was introduced when I put in the emit() call. What might I be doing wrong?

      Thanks...

      KroMignonK Offline
      KroMignonK Offline
      KroMignon
      wrote on last edited by
      #3

      @mzimmers said in Why is this a binding loop?:

      At runtime I get an error about a binding loop on "model." The error was introduced when I put in the emit() call. What might I be doing wrong?

      First you should understand how binding loops are detected, therefore take a look at this video from KDAB: Introduction to Qt / QML (Part 11) - Binding Loops.

      Now to solve your issue: remove the emit in the getter. You should only emit a notification on property value change, the purpose of this is to enable QML to be aware about changes. So property changes on C++ side can automatically trigger updates on QML side.
      If you trigger notification in C++ side with the getter, then:

      1. QML is reading property with getter
      2. QML is notified about property value change
      3. QML reread property value with getter
      4. QML is notified about property value change
      5. QML detect binding loop!

      It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

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

        Thank you both for the help. To answer your question about why there was a signal on a get -- the way this app was written, the get not only returned the current value, but also updated it first (I know it's weird).

        To fix this, I've created a setter for the property:

        QStringList ChangeConsumables::GetPosterModalChecklist() {
          return m_posterModalChecklist;
        }
        
        void ChangeConsumables::SetPosterModalChecklist(QStringList qsl) {
          m_posterModalChecklist = qsl;
          emit EventPosterModalChecklistChangedForQML(m_posterModalChecklist);
        }
        

        The code is a little convoluted, as the setter is actually invoked by another object (the same one that's providing the QStringList to the getter), but it seems to work.

        Thanks again...

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #5

          Hi,

          There's one thing missing from your setter: the equality guard. Usually the first thing done in a setter is check if the value changes and stop there if not. This allows to avoid signal storms were each party connected re-emits the same values over and over.

          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
          3
          • SGaistS SGaist

            Hi,

            There's one thing missing from your setter: the equality guard. Usually the first thing done in a setter is check if the value changes and stop there if not. This allows to avoid signal storms were each party connected re-emits the same values over and over.

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

            @SGaist so, like this?

            void ChangeConsumables::SetPosterModalChecklist(QStringList qsl) {
              if (m_posterModalChecklist != qsl) {
                  m_posterModalChecklist = qsl;
                  emit EventPosterModalChecklistChangedForQML(m_posterModalChecklist);
              }
            }
            
            1 Reply Last reply
            1
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #7

              Either that or

              void ChangeConsumables::SetPosterModalChecklist(QStringList qsl) {
                if (m_posterModalChecklist == qsl) {
                    return;
              }
                m_posterModalChecklist = qsl;
                emit EventPosterModalChecklistChangedForQML(m_posterModalChecklist);
              }
              

              Depending on your taste.
              Note that I have seen this version more frequently. Also in Qt's own sources.

              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
              • SGaistS SGaist

                Either that or

                void ChangeConsumables::SetPosterModalChecklist(QStringList qsl) {
                  if (m_posterModalChecklist == qsl) {
                      return;
                }
                  m_posterModalChecklist = qsl;
                  emit EventPosterModalChecklistChangedForQML(m_posterModalChecklist);
                }
                

                Depending on your taste.
                Note that I have seen this version more frequently. Also in Qt's own sources.

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

                @SGaist I realize I'm old school, but I really don't like return statements in the middle of a function. I know it's done by far better coders than I, but I'm just not a fan.

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #9

                  I understand your point.

                  IIRC, early returns like these may allow some optimization by the compiler.

                  It's technically also at least one less operation because != is usually implemented as ! ==.

                  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
                  0
                  • mzimmersM Offline
                    mzimmersM Offline
                    mzimmers
                    wrote on last edited by
                    #10

                    Not to be argumentative, but I'd venture that a routine that is comparing QStringList objects probably leaves much to be desired in the optimization department anyway.

                    Your comment about !== is interesting. Is there a way for the programmer to explicitly effect a similar comparison?

                    1 Reply Last reply
                    0
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #11

                      @mzimmers said in Why is this a binding loop?:

                      Not to be argumentative, but I'd venture that a routine that is comparing QStringList objects probably leaves much to be desired in the optimization department anyway.

                      I was more in the generic case of simple type comparison :-)

                      @mzimmers said in Why is this a binding loop?:

                      Your comment about !== is interesting. Is there a way for the programmer to explicitly effect a similar comparison?

                      I am not sure I am following you on that one.

                      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
                      0
                      • SGaistS SGaist

                        @mzimmers said in Why is this a binding loop?:

                        Not to be argumentative, but I'd venture that a routine that is comparing QStringList objects probably leaves much to be desired in the optimization department anyway.

                        I was more in the generic case of simple type comparison :-)

                        @mzimmers said in Why is this a binding loop?:

                        Your comment about !== is interesting. Is there a way for the programmer to explicitly effect a similar comparison?

                        I am not sure I am following you on that one.

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

                        @SGaist said in Why is this a binding loop?:

                        I am not sure I am following you on that one.

                        Well, of course C++ doesn't have a "!==" operator, so I assumed you meant that it first compares type, then content (a la Javascript). I was just curious how a C++ coder might perform that type check explicitly.

                        1 Reply Last reply
                        0
                        • SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on last edited by
                          #13

                          You missed the space between the ! and the == :-)

                          I meant it as: "!(a == b)"

                          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
                          0
                          • mzimmersM Offline
                            mzimmersM Offline
                            mzimmers
                            wrote on last edited by mzimmers
                            #14

                            Oh...I hate it when I do that (heh).

                            But now my statement on efficiency is even more true...

                            EDIT:

                            For those who really wish to exact that last bit of optimization, you could always do something like this:

                            void ChangeConsumables::SetPosterModalChecklist(QStringList qsl) {
                              do {
                                if (m_posterModalChecklist == qsl) {
                                  continue;
                                }
                                if (any other reasons to exclude further processing) {
                                  continue;
                                }
                                m_posterModalChecklist = qsl;
                                emit EventPosterModalChecklistChangedForQML(m_posterModalChecklist);
                              } while (false);
                            }
                            

                            This technique is also very handy for avoiding multiple if statements (with their annoying attendant indentation).

                            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