Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Item's enabled and visible properties and QML binding



  • Hi all,

    In the description of the "enabled" property of QML Item element there is the following paragraph:

    Setting this property directly affects the enabled value of child items. When set to false, the enabled values of all child items also become false. When set to true, the enabled values of child items are returned to true, unless they have explicitly been set to false.

    (and the same is stated in the description of "visible" property). I wonder, does it break property bindings? I wrote a small test:

    import QtQuick 2.12
    import QtQuick.Controls 2.5
    import QtQuick.Window 2.12
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        Column {
            id: column
            anchors.centerIn: parent
    
            Text {
                id: text
                text: "TEXT"
    
                states: [
                    State {
                        name: "visibleBind"
    
                        PropertyChanges {
                            target: text
                            visible: timer.textVisibility
                            enabled: timer.textVisibility
                        }
                    },
                    State {
                        name: "visibleForceUnbind"
    
                        PropertyChanges {
                            target: text
                            visible: timer.textVisibility
                            enabled: timer.textVisibility
                        }
                    }
                ]
    
                onVisibleChanged: {
                    console.log("VISIBLE: " + visible);
                }
    
                onEnabledChanged: {
                    console.log("ENABLED: " + enabled);
                }
            }
        }
    
        Row {
            anchors.bottom: parent.bottom
            anchors.horizontalCenter: parent.horizontalCenter
    
            Button {
                text: "VISIBILITY"
    
                onClicked: {
                    column.visible = !column.visible;
                    column.enabled = !column.enabled;
                }
            }
    
            Button {
                text: "BIND"
    
                onClicked: {
                    text.state = "visibleBind";
                }
            }
    
            Button {
                text: "BREAK"
    
                onClicked: {
                    text.state = "visibleForceUnbind";
                    text.visible = false;
                    text.enabled = false;
                }
            }
        }
    
        Timer {
            id: timer
            interval: 1000
            repeat: true
            running: true
    
            property bool textVisibility: false
    
            onTriggered: {
                textVisibility = !textVisibility;
            }
        }
    }
    

    and it looks like this behaviour doesn't break bindings (changing of property values stops after clicking on "VISIBILITY" button, but resumes after clicking on it again), but is this a part of contract? I mean, is this a documented behaviour and not expected to change between versions? The paragraph quoted above is not very clear on this point.

    Thanks in advance for your help.



  • OK, it looks like I got this. Roughly speaking, there are two states of any property: static value and binding. If property contains static value, then state machinery remember it as static value (and it doesn't matter, was this value inherited from parent or not, it always just remember current value as static value). If property contains binding, then it will be remembered as binding (and state machinery doesn't care about momentary resulting value of this binding).



  • This post is deleted!


  • It looks like the better wording would be "unless this property have explicitly been set to specific value in child item, in which case it will return to this value" or something like this. Not just in terms of static true/false values, which looks misleading.



  • @KoneTaH Yes! as you said the property bindings of children would be retrieved when visibility/enabled property of parent is set to true.



  • OK, here is another one puzzle:

    import QtQuick 2.12
    import QtQuick.Controls 2.5
    import QtQuick.Window 2.12
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        Column {
            id: column
            anchors.centerIn: parent
    
            Text {
                id: text
                text: "TEXT"
                visible: true
    
                states: [
                    State {
                        name: "setVisible"
    
                        PropertyChanges {
                            target: text
                            visible: true
                        }
                    },
                    State {
                        name: "restoreVisible"
                    }
                ]
    
                onVisibleChanged: {
                    console.log("VISIBLE: " + visible);
                }
            }
        }
    
        Row {
            anchors.bottom: parent.bottom
            anchors.horizontalCenter: parent.horizontalCenter
            spacing: 16
    
            Button {
                text: "TOGGLE COLUMN VISIBILITY"
    
                onClicked: {
                    column.visible = !column.visible;
                }
            }
    
            Button {
                text: "SET TEXT VISIBILITY"
    
                onClicked: {
                    text.state = "setVisible";
                }
            }
    
            Button {
                text: "RESTORE TEXT VISIBILITY"
    
                onClicked: {
                    text.state = "restoreVisible";
                }
            }
        }
    
        Timer {
            id: timer
            interval: 1000
            repeat: true
            running: true
    
            property bool textVisibility: false
    
            onTriggered: {
                textVisibility = !textVisibility;
            }
        }
    }
    
    1. Suppose that we run this app and then click on "TOGGLE COLUMN VISIBILITY" button. Text.visible become false.
    2. Then we click on "SET TEXT VISIBILITY" button. Text goes into "setVisible" state and remember that previous state included visible=false.
    3. Then we click on "TOGGLE COLUMN VISIBILITY" button again. Column become visible and text too.
    4. Then we click on "RESTORE TEXT VISIBILITY" button. Text goes from "setVisible" state (resetting visible property to memorized value, which is false) to "restoreVisible" state and become invisible.

    So far so good. Then we make following changes to our code:

            Text {
                id: text
                text: "TEXT"
    -           visible: true
    +           visible: timer.textVisibility
    

    and repeat our experiments:

    1. Run this app and see a blinking text, which is expected.
    2. Click on "TOGGLE COLUMN VISIBILITY" button. Text.visible become false. OK, this is expected too.
    3. Then we click on "SET TEXT VISIBILITY" button. Text goes into "setVisible" state and should remember that previous state included visible=false (just like in previous case, as I think).
    4. Then we click on "TOGGLE COLUMN VISIBILITY" button again. Column become visible and text too (but it doesn't blink). Just as expected.
    5. Then we click on "RESTORE TEXT VISIBILITY" button. Text goes from "setVisible" state and should reset visible property to false (which was memorized at step 3) to "restoreVisible" state and become invisible, but it's not the case! Instead it start blinking again, so it looks like that on step 3 it remember property binding instead of actual value.

    Why such a discrepancy here?



  • OK, it looks like I got this. Roughly speaking, there are two states of any property: static value and binding. If property contains static value, then state machinery remember it as static value (and it doesn't matter, was this value inherited from parent or not, it always just remember current value as static value). If property contains binding, then it will be remembered as binding (and state machinery doesn't care about momentary resulting value of this binding).


Log in to reply