Keep GridView element in front of others during animation



  • Hello, I'm trying to understand how to maintain an element of a GridView on top of others during a ParentAnimation. I think it's best explained with this snippet, which I beg you to try out:
    @import QtQuick 2.2

    Item {
    width: 400; height: 400
    id: main

    GridView {
    id: grid
    anchors.fill: parent
    cellWidth: width / Math.sqrt(model)
    cellHeight: height / Math.sqrt(model)

    model: 9
    delegate: Rectangle {
    id: rect
    width: grid.cellWidth
    height: grid.cellHeight
    color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)

    Text {
    anchors.centerIn: parent
    text: "ABABAB"
    wrapMode: Text.WrapAtWordBoundaryOrAnywhere
    }

    MouseArea {
    anchors.fill: parent
    onClicked:
    {
    if (rect.state != "fullScreen")
    rect.state = "fullScreen";
    else
    rect.state = "";
    }
    }

    states: [
    State {
    name: "fullScreen"
    ParentChange {
    target: rect
    parent: main
    width: parent.width
    height: parent.height
    x: 0
    y: 0
    }
    }
    ]

    transitions: [
    Transition {
    ParentAnimation {
    NumberAnimation { properties: "x, y, width, height"; duration: 500; easing.type: Easing.InQuad }
    }
    }
    ]
    }
    }
    }
    @
    In practice, I zoom the selected element by changing its parent so that it can extend beyond the cell boundaries. And the zooming-in animation works fine: the rectangle is always painted on top of the others.
    When zooming back though, the first thing that happens is that the parent is changed back to the gridview, therefore the rectangle is painted above previous elements but below the successive ones (in fact, the 1st element, at the top left, is always painted below all other elements whereas the 9th element, at the bottom right, is always painted like I want during the zooming-out animation).

    How can I solve this problem? I came up with a solution but thinking in an imperative way, not in a declarative way like QML requires...



  • Here is one simple way to do it. I introduced a "current" property and declared that if the clicked item is current, its z-order is higher than the other rects. This will ensure that the clicked item is always at the top of the painting stack even when the item is reparented back into the grid.

    @
    Item {
    width: 400; height: 400
    id: main
    property var current
    GridView {
    id: grid
    anchors.fill: parent
    cellWidth: width / Math.sqrt(model)
    cellHeight: height / Math.sqrt(model)

        model: 9
        delegate: Rectangle {
            id: rect
            width: grid.cellWidth
            height: grid.cellHeight
            color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
            z: rect === current ? 100 : 0
    
            Text {
                anchors.centerIn: parent
                text: "ABABAB"
                wrapMode: Text.WrapAtWordBoundaryOrAnywhere
            }
    
            MouseArea {
                anchors.fill: parent
                onClicked:
                {
                    current = rect
                    if (rect.state != "fullScreen")
                        rect.state = "fullScreen";
                    else
                        rect.state = "";
                }
            }
    
            states: [
                State {
                    name: "fullScreen"
                    ParentChange {
                        target: rect
                        parent: main
                        width: parent.width
                        height: parent.height
                        x: 0
                        y: 0
                    }
                }
            ]
    
            transitions: [
                Transition {
                    ParentAnimation {
                        NumberAnimation { properties: "x, y, width, height"; duration: 500; easing.type: Easing.InQuad  }
                    }
                }
            ]
        }
    }
    

    }
    @



  • I've got no solution yet but you could try to handle the z-achsis of your delegate. That should work out fine.



  • [quote author="Jens" date="1392024205"]Here is one simple way to do it. I introduced a "current" property and declared that if the clicked item is current, its z-order is higher than the other rects. This will ensure that the clicked item is always at the top of the painting stack even when the item is reparented back into the grid.

    @
    Item {
    width: 400; height: 400
    id: main
    property var current
    GridView {
    id: grid
    anchors.fill: parent
    cellWidth: width / Math.sqrt(model)
    cellHeight: height / Math.sqrt(model)

        model: 9
        delegate: Rectangle {
            id: rect
            width: grid.cellWidth
            height: grid.cellHeight
            color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
            z: rect === current ? 100 : 0
    
            Text {
                anchors.centerIn: parent
                text: "ABABAB"
                wrapMode: Text.WrapAtWordBoundaryOrAnywhere
            }
    
            MouseArea {
                anchors.fill: parent
                onClicked:
                {
                    current = rect
                    if (rect.state != "fullScreen")
                        rect.state = "fullScreen";
                    else
                        rect.state = "";
                }
            }
    
            states: [
                State {
                    name: "fullScreen"
                    ParentChange {
                        target: rect
                        parent: main
                        width: parent.width
                        height: parent.height
                        x: 0
                        y: 0
                    }
                }
            ]
    
            transitions: [
                Transition {
                    ParentAnimation {
                        NumberAnimation { properties: "x, y, width, height"; duration: 500; easing.type: Easing.InQuad  }
                    }
                }
            ]
        }
    }
    

    }
    @
    [/quote]

    Thanks Jens, I had indeed previously tried to play with the z coordinate in my main app (the above is just a snippet that somehow follows the structure of the main app), more precisely by giving the Transition an id and setting, inside Rectangle rect, the following:
    @z: transition.running ? 100 : 0@
    This didn't work with my main app but indeed works with the simple example as well as your solution does.
    Maybe the problem is due to the fact that the delegate in my app is actually a Flipable.

    Now, I just came up with the solution: I have to bind the flipable's z with this mechanism to get the result I want!

    This code doesn't work:
    @import QtQuick 2.2

    Item {
    width: 400; height: 400
    id: main

    GridView {
    id: grid
    anchors.fill: parent
    cellWidth: width / Math.sqrt(model)
    cellHeight: height / Math.sqrt(model)

    model: 9
    delegate: Flipable {
    width: grid.cellWidth
    height: grid.cellHeight

    front: Rectangle {
    id: rect
    width: parent.width
    height: parent.height
    z: fullScreenTransition.running ? 100 : 0
    color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)

    Text {
     anchors.centerIn: parent
     text: "ABABAB"
     wrapMode: Text.WrapAtWordBoundaryOrAnywhere
    }
    
    MouseArea {
     anchors.fill: parent
     onClicked:
     {
      if (rect.state != "fullScreen")
       rect.state = "fullScreen";
      else
       rect.state = "";
     }
    }
    
    states: [
     State {
      name: "fullScreen"
      ParentChange {
       target: rect
       parent: main
       width: parent.width
       height: parent.height
       x: 0
       y: 0
      }
     }
    ]
    
    transitions: [
     Transition {
      id: fullScreenTransition
      ParentAnimation {
       NumberAnimation { properties: "x, y, width, height"; duration: 500; easing.type: Easing.InQuad  }
      }
     }
    ]
    

    }
    }
    }
    }
    @

    This code does!
    @import QtQuick 2.2

    Item {
    width: 400; height: 400
    id: main

    GridView {
    id: grid
    anchors.fill: parent
    cellWidth: width / Math.sqrt(model)
    cellHeight: height / Math.sqrt(model)

    model: 9
    delegate: Flipable {
    width: grid.cellWidth
    height: grid.cellHeight
    z: fullScreenTransition.running ? 100 : 0

    front: Rectangle {
    id: rect
    width: parent.width
    height: parent.height

    color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
    
    Text {
     anchors.centerIn: parent
     text: "ABABAB"
     wrapMode: Text.WrapAtWordBoundaryOrAnywhere
    }
    
    MouseArea {
     anchors.fill: parent
     onClicked:
     {
      if (rect.state != "fullScreen")
       rect.state = "fullScreen";
      else
       rect.state = "";
     }
    }
    
    states: [
     State {
      name: "fullScreen"
      ParentChange {
       target: rect
       parent: main
       width: parent.width
       height: parent.height
       x: 0
       y: 0
      }
     }
    ]
    
    transitions: [
     Transition {
      id: fullScreenTransition
      ParentAnimation {
       NumberAnimation { properties: "x, y, width, height"; duration: 500; easing.type: Easing.InQuad  }
      }
     }
    ]
    

    }
    }
    }
    }
    @

    :))



  • It makes sense because z-values are only relevant when comparing items that have the same parent. Since Flippable are all direct children of the GridView, they are painted in order according to the z-value you have set on the Flippable itself.

    When you assign the back or front properties of the Flippable itself, you are actually assigning a child of the flippable, and setting the z-value of a child has no effect on the painting order of its parent. Each node is also drawing all of its children before the next node is considered so the only thing you can effect by setting the z-value of the back item is which order you draw the back vs front Flippable items.

    @
    GridView
    | |
    Delegate1 Delegate2
    | | | |
    Back Front Back Front
    @



  • Thanks for the insight Jens! Very interesting :)



  • Thanks for the insight Jens! Very interesting :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.