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. False binding loop?

False binding loop?

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
10 Posts 3 Posters 2.6k 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.
  • V Offline
    V Offline
    vlada
    wrote on last edited by
    #1

    Hi,

    since Qt 5.10.1 I'm getting this warning: Binding loop detected for property "textLengthType"

    I post here rather the whole code. It's quite long but I'll try to explain shortly what I'm doing here. I have a menu at bottom of my app and I want to show only an icon, a short text or a long text, depending on the space available. The variable textLengthType holds which of these 3 text types should be displayed.

    I don't think there is anything wrong in my code. Is this is a false positive warning or is there a mistake?

    import QtQuick 2.6
    
    Row {
        property int buttonWidth: textLengthType == 1 ? maxTextSize+units.gu(4) : textLengthType == 2 ? maxTextSizeShort+units.gu(4) : main.width/(itemsCount+1)
        property int distance: (main.width-itemsCount*buttonWidth)/(itemsCount+1)
        property int active: -1
        property int itemsCount: 4
        property int maxTextSize: Math.max(text1.width, text2.width, text3.width, text4.width)
        property int maxTextSizeShort: Math.max(text1.width, text5.width, text6.width, text7.width)
        property int textLengthType: (maxTextSize+units.gu(5))*itemsCount < main.width ? 1 : (maxTextSizeShort+units.gu(5))*itemsCount < main.width ? 2 : 3
        anchors.leftMargin: distance
        anchors.rightMargin: distance
        spacing: distance
    
        function showActive() {
            active = 0;
        }
    
        function hideActive() {
            active = -1;
        }
    
    
        Rectangle {
            width: buttonWidth
            height: parent.height-units.gu(2)
            color: "#00000000"
            border.width: units.dp(2)
            border.color: active == 0 ? main.selectionColor : "#00000000"
            radius: buttonWidth/8
    
            ToolbarButton {
                width: buttonWidth
                height: parent.height
                iconSource:"images/check.svg"
                text: textLengthType == 3 ? "" : qsTr("Apply")
                onTriggered: {
                    settingsTab.apply()
                }
            }
        }
    
        Rectangle {
            width: buttonWidth
            height: parent.height-units.gu(2)
            color: "#00000000"
            border.width: units.dp(2)
            border.color: active == 1 ? main.selectionColor : "#00000000"
            radius: buttonWidth/8
    
            ToolbarButton {
                width: buttonWidth
                height: parent.height
                iconSource:"images/cancel.svg"
                text: textLengthType == 1 ? qsTr("Cancel Changes") : textLengthType == 2 ? qsTr("Cancel") : ""
                onTriggered: {
                    settingsTab.cancel()
                }
            }
        }
    
        Rectangle {
            width: buttonWidth
            height: parent.height-units.gu(2)
            color: "#00000000"
            border.width: units.dp(2)
            border.color: active == 2 ? main.selectionColor : "#00000000"
            radius: buttonWidth/8
    
            ToolbarButton {
                width: buttonWidth
                height: parent.height
                iconSource:"images/import.svg"
                text: textLengthType == 1 ? qsTr("Import Settings") : textLengthType == 2 ? qsTr("Import") : ""
                onTriggered: {
                    settingsTab.importSettings()
                }
            }
        }
    
        Rectangle {
            width: buttonWidth
            height: parent.height-units.gu(2)
            color: "#00000000"
            border.width: units.dp(2)
            border.color: active == 3 ? main.selectionColor : "#00000000"
            radius: buttonWidth/8
    
            ToolbarButton {
                width: buttonWidth
                height: parent.height
                iconSource:"images/export.svg"
                text: textLengthType == 1 ? qsTr("Export Settings") : textLengthType == 2 ? qsTr("Export") : ""
                onTriggered: {
                    settingsTab.exportSettings()
                }
            }
        }
        TextMetrics {
            id: text1
            font.pixelSize: config.verySmallFontSize
            text: qsTr("Apply")
        }
    
        TextMetrics {
            id: text2
            font.pixelSize: config.verySmallFontSize
            text: qsTr("Cancel Changes")
        }
    
        TextMetrics {
            id: text3
            font.pixelSize: config.verySmallFontSize
            text: qsTr("Import Settings")
        }
    
        TextMetrics {
            id: text4
            font.pixelSize: config.verySmallFontSize
            text: qsTr("Export Settings")
        }
    
        TextMetrics {
            id: text5
            font.pixelSize: config.verySmallFontSize
            text: qsTr("Cancel")
        }
    
        TextMetrics {
            id: text6
            font.pixelSize: config.verySmallFontSize
            text: qsTr("Import")
        }
    
        TextMetrics {
            id: text7
            font.pixelSize: config.verySmallFontSize
            text: qsTr("Export")
        }
    }
    
    
    1 Reply Last reply
    0
    • V Offline
      V Offline
      vlada
      wrote on last edited by
      #2

      Nobody has an idea? So I'll try to make a stripped down version and report it as a bug.

      J.HilkJ 1 Reply Last reply
      0
      • V vlada

        Nobody has an idea? So I'll try to make a stripped down version and report it as a bug.

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

        @vlada hi,
        usually I would say, no, not a false positive.

        try to replace the ToolbarButton geometry with something differen

        //from 
        ToolbarButton {
                    width: buttonWidth
                    height: parent.height
                    iconSource:"images/export.svg"
                    ....
        }
        //to
        ToolbarButton {
                    anchors.fill: parent
                    iconSource:"images/export.svg"
                    ....
        }
        

        see if that helps.


        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
        0
        • V Offline
          V Offline
          vlada
          wrote on last edited by
          #4

          That indeed fixes the problem but then it won't work as expected. So it is not a solution.

          I just found out that it only happens on Android. If I compile the same application with the same Qt 5.10.1 but on desktop (Windows) I don't get the warning. I think this makes it more obvious that the problem is probably not in my code.

          J.HilkJ 1 Reply Last reply
          0
          • V vlada

            That indeed fixes the problem but then it won't work as expected. So it is not a solution.

            I just found out that it only happens on Android. If I compile the same application with the same Qt 5.10.1 but on desktop (Windows) I don't get the warning. I think this makes it more obvious that the problem is probably not in my code.

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

            @vlada said in False binding loop?:

            That indeed fixes the problem but then it won't work as expected. So it is not a solution.

            how does it behave differently?
            You don't specify a x or y in your toolbutton so it defaults to 0

            and

            ToolbarButton {
                 x: 0
                 y:0
                 width: buttonWidth //parent.width == buttonWidth in your case
                 height: parent.height
            }
            

            should be the same as

            ToolbarButton {
                anchors.fill: parent  
            }
            

            I just found out that it only happens on Android. If I compile the same application with the same Qt 5.10.1 but on desktop (Windows) I don't get the warning. I think this makes it more obvious that the problem is probably not in my code.

            That is indeed strange!


            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
            0
            • V Offline
              V Offline
              vlada
              wrote on last edited by
              #6

              The ToolbarButton is a component for bottom menu with buttons and text, it was introduced in Ubuntu Touch and I made my own implementation for other OSs.

              The 5 buttons are in a Row component, which sets the x property. Of course I could have set the ToolbarButton to anchors.fill: parent. I suppose I did it this way because of Ubuntu Touch (which is now obsolete) compatibility. But changing it only here won't bring anything. I would have to replace the buttonWidth property completely.

              Anyway the problem is in the textLengthType property, not the buttonWidth. I made a test application with exactly this code and I can not reproduce it! Very weird and annoying issue.

              There are no problems regarding function, everything works as intended. I just get these warnings in console. To see how it looks like, have a look at this screenshot. The component in my code is the bottom menu.

              I found a workaround to the issue. You can see that I calculate the maximum text size for the short and long variants. It is stored to variables maxTextSize and maxTextSizeShort. Some of the TextMetrics items are used in both because there is only one text variant for both cases. But if I duplicate them so that each item is used only once, I don't get this warning anymore. Do you see there any logic? I don't. :-(

              J.HilkJ 1 Reply Last reply
              0
              • V vlada

                The ToolbarButton is a component for bottom menu with buttons and text, it was introduced in Ubuntu Touch and I made my own implementation for other OSs.

                The 5 buttons are in a Row component, which sets the x property. Of course I could have set the ToolbarButton to anchors.fill: parent. I suppose I did it this way because of Ubuntu Touch (which is now obsolete) compatibility. But changing it only here won't bring anything. I would have to replace the buttonWidth property completely.

                Anyway the problem is in the textLengthType property, not the buttonWidth. I made a test application with exactly this code and I can not reproduce it! Very weird and annoying issue.

                There are no problems regarding function, everything works as intended. I just get these warnings in console. To see how it looks like, have a look at this screenshot. The component in my code is the bottom menu.

                I found a workaround to the issue. You can see that I calculate the maximum text size for the short and long variants. It is stored to variables maxTextSize and maxTextSizeShort. Some of the TextMetrics items are used in both because there is only one text variant for both cases. But if I duplicate them so that each item is used only once, I don't get this warning anymore. Do you see there any logic? I don't. :-(

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

                @vlada said in False binding loop?:

                There are no problems regarding function, everything works as intended. I just get these warnings in console. To see how it looks like, have a look at this screenshot. The component in my code is the bottom menu.

                Well they are not warnings, they are actuall errors. It detected, that the property changes its value again, weil it's still updating all bound properties and values during the eventloop cycle and - to prevent a deadlock - breaks the loop by stopping the property calculation/update.
                This could stop in an state, that represents your expected result, but it might just as well not. That's more or less random. Firstupdate always wins

                I found a workaround to the issue. You can see that I calculate the maximum text size for the short and long variants. It is stored to variables maxTextSize and maxTextSizeShort. Some of the TextMetrics items are used in both because there is only one text variant for both cases. But if I duplicate them so that each item is used only once, I don't get this warning anymore. Do you see there any logic? I don't. :-(

                I think I do, when a property calculates the initial value or gets chaged, all properties influenzed or bound to that property update as well

                //assume
                property bool c : a < b
                property int i : c*100
                

                c gets updated when a changes and updates again wenn b changes, and therefore i gets updated when a changes and again when b changes.

                What I'm trying to say,
                the most common error you'll have with QML are binding loops and in 99.99 % of all cases those are not false detections or qml errors, but the human coder created made them. Usually by accident.


                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
                0
                • M Offline
                  M Offline
                  Maheshdev305
                  wrote on last edited by
                  #8

                  Instead of a Row, try using an RowLayout.
                  Set the minimum and maximum width of the ToolbarButtons and ensure to set the property fillWidth as true.

                  1 Reply Last reply
                  0
                  • V Offline
                    V Offline
                    vlada
                    wrote on last edited by
                    #9

                    @J-Hilk Yes, I understand that and if it would be just a useless warning I wouldn't care about that. I know it is an actual error. But I just don't see it. And furthermore I didn't get the error before Qt 5.10, it only happens on Android and disappears after a change in code which don't change the actual functionality at all. All this makes me believe the fault is not in my code.

                    This is how the affected property is calculated:

                    1. Calculate TextMetrics for all the texts
                    2. Get the longest one (for both short and long variants)
                    3. Compare if the the texts are not too long to fit in current width and decide which type to show (no text, short text, long text)

                    I don't see a binding loop in this calculation.

                    @Maheshdev305 Thanks for the hint. I'll try that if it makes any change. Basically I know how to fix it and avid the error. It just doesn't make much sense.

                    1 Reply Last reply
                    0
                    • V Offline
                      V Offline
                      vlada
                      wrote on last edited by vlada
                      #10

                      I think I finally found the reason why I'm getting the error. I changed too many things at once and did a wrong conclusion.

                      So the real problem is that the TextMetrics objects are inside the row and are probably affected by it. I think they shouldn't, but it just happens. The solution is to remove them from the row.

                      Why this only happens on Android and since Qt 5.10, I have no idea. But at least I have a solution.

                      1 Reply Last reply
                      1

                      • Login

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