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.2k 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.
  • mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by
    #1

    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 1 Reply Last reply
    0
    • 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