3
votes

I want to show/hide an element by modifying it's height. Here is an example code showing my issue:

import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4

Window {
    id: win
    width: 300
    height: 300
    visible: true

    ColumnLayout {
        width: parent ? parent.width : 200


        Switch {
            id: someswitch
            Layout.alignment: Qt.AlignCenter
        }

        Label {
            id: myText
            text: "dummy"
            height: 0

            wrapMode: Text.WordWrap
            clip: true
            Layout.fillWidth: true
            Layout.alignment: Qt.AlignCenter

            states: State {
                name: "visible"
                when: someswitch.checked
                PropertyChanges { target: myText; height: implicitHeight }
            }

            Behavior on height {
                NumberAnimation { duration: 100 }
            }
        }
    }
}

I didn't add a Transition/Animation yet, but the behavior is already wrong on this stage. someswitch is unchecked by default but the text is shown. On the other hand, after checking the switch, the text hides and never appears back.

How should I handle that? I'd like the text to "slide out". I don't want to change its opacity.

2

2 Answers

4
votes

Generally speaking, States consistency should be guaranteed to ensure that Transitions work properly. Consistency can be achieved either:

  • by defining a consistent default state
  • by defining all the necessary States, like the other nice answer proposed.

That begin said, it should be noted that the presence of a Layout plays a key role here. The Layout somewhat supersedes the height settings of the Items with its minimumHeight property. In such a scenario States defined over height does not really affect the Label. The obvious solution is to force States consistency but over Layout.preferredHeight, i.e. define the default State as well as the "invisible" with different values for Layout.preferredHeight instead of height. A revisited version of your code could look like this:

Label {
    id: myText
    text: "dummy"
    wrapMode: Text.WordWrap
    clip: true
    Layout.fillWidth: true
    Layout.alignment: Qt.AlignCenter
    Layout.preferredHeight: implicitHeight   //visible --> layout height = text implicit height

    states: State {
            name: "invisible"
            when: !someswitch.checked
            PropertyChanges { target: myText; Layout.preferredHeight: 0 }  // invisible --> layout item height forced to zero
        }

    Behavior on Layout.preferredHeight {
        NumberAnimation { duration: 100 }
    }
}

A fully working example can be found here (whereas a version with a "visible" state can be found here).

1
votes

You should use States and Transition in your case. For example:

import QtQuick 2.4
import QtQuick.Window 2.0
import QtQuick.Controls 1.2

Window {
    id: mainWindow
    width: 600
    height: 600
    visible: true

    CheckBox {
        text: "hide/show"
        id: someswitch
        x: 10
        y: 10
    }

    Rectangle {
        id: mytext
        width: parent.width
        anchors.centerIn: parent
        color: "orange"
        state: "shown"
        states: [
            State {
                name: "shown"
                when: !someswitch.checked
                PropertyChanges { target: mytext; height: 300 }
            },
            State {
                name: "hidden"
                when: someswitch.checked
                PropertyChanges { target: mytext; height: 0 }
            }
        ]
        transitions: Transition {
             PropertyAnimation { property: "height"; duration: 500; easing.type: Easing.InOutQuad }
        }
    }
}