qmlnested-loopsinotifypropertychangedfunction-call

How to resolve this loop call caused by property changed in qml, can I stop binding somewhere?


import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    property int anum: 0
    property int bnum: 1

    onAnumChanged: {
        bnum+=1
    }

    onBnumChanged: {
        anum+=1
        //Is there some way to stop loop call ?
        //in widget we can unconnect some signal and slot
        //but how to disconnect in qml
    }

    Button{
        text:"begain"
        onClicked: {
            anum=anum+1
        }
    }

}
  1. when i push the button
  2. the 'anum' change to 1
  3. then the function onAnumChanged begain to execute
  4. then the bnum has been changed
  5. then the onBnumChanged begain to execute
  6. then the anum has been changed
  7. then loop from 3 to 7

is there some way to stop this?can i use some unbinding function to stop this like 'disconnect(sender,signal,receiver,slot)' in c++(widget)


Solution

  • Several things are needed to help break the binding loop:

    1. Check a break flag as smr has suggested
    2. Allow events, use Qt.callLater() means idle time is granted so events can fire
    3. Define events that reset and set the break flag

    We can borrow the userbreak pattern and implement here with mouse tapped, keypress and even visibility changing as things that will raise a userbreak.

    import QtQuick
    import QtQuick.Controls
    Page {
        width: 640
        height: 480
        visible: true
        title: qsTr("Hello World")
    
        property int anum: 0
        property int bnum: 1
        property bool userbreak: false
    
        onAnumChanged: {
            if (userbreak) return;
            Qt.callLater( () => { bnum++ } );
        }
    
        onBnumChanged: {
            if (userbreak) return;
            Qt.callLater( () => { anum++ } );
            //Is there some way to stop loop call ?
            //in widget we can unconnect some signal and slot
            //but how to disconnect in qml
        }
    
        Button{
            text: "begain %1 %2".arg(anum).arg(bnum)
            onClicked: {
                userbreak = false;
                Qt.callLater( () => { anum++ } );
            }
        }
    
        TapHandler {
            onTapped: userbreak = true;
        }
    
        Keys.onPressed: {
            userbreak = true;
        }
    
        onVisibleChanged: {
            userbreak = true;
        }
    }
    

    You can Try it Online!