user3417815
user3417815

Reputation: 635

QtQuick 2 - Side Panel example

Can someone help me to understand behaviour of this code? I wrote simple example of side panel menu (just template now) and there is problem to use onMenuVisibleChanged slot (but all I need actually works, just want to understand why another way don't). Logically it should change x of panel rectangle to specified values, but it didn't. Please help me ot understand correct approach for this thing.

main.qml

import QtQuick 2.3
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2

ApplicationWindow {
    title: qsTr("Hello World")
    width: 640
    height: 480
    visible: true
    menuBar: MenuBar{
        Menu{
            title: "File"
        MenuItem{
            text: "Exit"
            onTriggered: Qt.quit()
        }
        }
    }
    SidePane{
        id: sidePane
        menuWidth: 350
        z: 2
    }
}

SidePane.qml

import QtQuick 2.3
import QtQuick.Window 2.2

Item {
    id: screenItem
    anchors.fill: parent
    function show() {
        rect.x = 0
        menuVisible = true
    }
    function hide() {
        rect.x = -rect.width
        menuVisible = false
    }
    property int animationDuration: 200
    property bool menuVisible: false
    property int dragThreshold: 120
    property int menuWidth: 300
    Rectangle {
        id: rect
        width: menuWidth
        x: -rect.width
        height: Screen.height
        color: "lightsteelblue"
        Drag.active: menuDragArea.drag.active
        Behavior on x {
            NumberAnimation {
                duration: animationDuration
                easing.type: Easing.InOutQuad
            }
        }
        MouseArea {
            property int dragX: 0
            property int startX: 0
            property int diffX: 0
            id: menuDragArea
            hoverEnabled: true
            height: rect.height
            width: rect.width + 40
            anchors.left: rect.left
            drag.target: rect
            drag.axis: Drag.XAxis
            drag.minimumX: -rect.width
            drag.maximumX: 0
            onPressed: startX = rect.x + rect.width
            onReleased: {
                dragX = rect.x + rect.width
                diffX = Math.abs(startX - dragX)
                if ((diffX > dragThreshold) && (startX == 0)){
                    rect.x = 0
                    menuVisible = true
                } else if ((diffX < dragThreshold) && (startX == 0)){
                    rect.x = -rect.width
                    menuVisible = false
                }
                if ((diffX > dragThreshold) && (startX == rect.width)){
                    rect.x = -rect.width
                    menuVisible = false
                } else if ((diffX < dragThreshold) && (startX == rect.width)){
                    rect.x = 0
                    menuVisible = true
                }
            }
        }
    }
    Rectangle{
        id: shadowRect
        anchors.left: rect.right
        anchors.right: screenItem.right
        opacity: (rect.x + rect.width) / (rect.width * 2.2)
        color: "black"
        height: screenItem.height
        MouseArea{
            id: shadowArea
            anchors.fill: shadowRect
            visible: menuVisible ? true : false
            hoverEnabled: true
            onClicked: {
                if (menuVisible == true){
                    rect.x = -rect.width
                    menuVisible = false
                }
            }
        }
        Rectangle{
            id: shadowRect2
            color: "black"
            anchors.left: parent.left
            width: 5
            opacity: (rect.x + rect.width) / (rect.width * 2)
            height: screenItem.height
        }
        Rectangle{
            id: shadowRect3
            color: "black"
            anchors.left: parent.left
            width: 3
            opacity: (rect.x + rect.width) / (rect.width * 1.9)
            height: screenItem.height
        }
    }
    onMenuVisibleChanged: menuVisible ? rect.x = 0 : rect.x = -rect.width
}

Appreciate any help. Just a QML beginner. The most purpose is to use this panel in android application. Feel free to use this code if you want.

Upvotes: 3

Views: 1600

Answers (1)

siusiulala
siusiulala

Reputation: 1070

The property drag make the x value draggable

if you implement it by mouseX onPressed/onReleased, rect.x will be 0 or -rect.width onMenuVisibleChanged

MouseArea {
        property int dragX: 0
        property int startX: 0
        property int diffX: 0
        id: menuDragArea
        hoverEnabled: true
        height: rect.height
        width: rect.width + 40
        anchors.left: rect.left

        onPressed: {
            startX = mouseX;
            console.log(rect.x)
        }
        onReleased: {
            diffX = Math.abs(startX - mouseX)
            console.log("diff:"+diffX)
            if ((diffX > dragThreshold) && (mouseX > startX) && (rect.x !=0 )){
                rect.x = 0
                menuVisible = true
            } else if ((diffX > dragThreshold) && (mouseX < startX) && (rect.x == 0)){
                rect.x = -rect.width
                menuVisible = false
            }
        }
    }

with visual drag ,sorry it's ugly:

MouseArea {
        property int startX: 0
        property int diffX: 0
        property int startRectX: 0
        property bool isPressed: false
        id: menuDragArea
        hoverEnabled: true
        height: rect.height
        width: rect.width + 40
        anchors.left: rect.left
        onPressed: {
            startX = mouseX;
            startRectX = rect.x
            isPressed = true
            console.log(rect.x)}
        onMouseXChanged: {
            if(isPressed)
                rect.x = (mouseX>rect.width)? 0 : (mouseX-rect.width)
        }
        onReleased: {
            isPressed = false
            diffX = Math.abs(startX - mouseX)
            console.log("diff:"+diffX)
            if ((mouseX >= startX) && (startRectX == -rect.width )){
                if(diffX > dragThreshold)
                {
                    rect.x = 0
                    menuVisible = true
                }
                else
                    rect.x = startRectX
            } else if ((mouseX <= startX) && (startRectX == 0)){
                if(diffX > dragThreshold)
                {
                    rect.x = -rect.width
                    menuVisible = false
                }
                else
                    rect.x = startRectX
            }
            else
                rect.x = startRectX
        }
    }

Upvotes: 2

Related Questions