Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drag after long press

I want to drag my custom buttons QML after a long press over them. I've implemented that behaviour, however the problem is that after enabling drag, I need to press button once again to actually start dragging. How should I implement this mechanism if I want to move buttons without releasing after long press?

Here is my button code (onReleased and onLongPressed are my own signals):

ButtonWidget.SoftButtonUI
{
    id:softButtonDelegate2
    x:500
    y:300
    labelText: "button"
    iconImageSource: path
    isGrayedOut: false

    Drag.active: dragArea2.drag.active
    Drag.hotSpot.x: 10
    Drag.hotSpot.y: 10
    onReleased:
    {
        console.log("onClicked")
    }

    onLongPressed:
    {
        console.log("onLongPressed")
        dragArea2.enabled = true
    }

    MouseArea {
        id: dragArea2
        enabled: false
        anchors.fill: parent
        drag.target: parent
        onReleased: parent.Drag.drop()
        onClicked: {
            console.log("MouseArea onClicked")
        }
        onPressAndHold: {
            console.log("MouseArea  onPressAndHold")
        }
    }
}

Any idea?

like image 740
hus Avatar asked Nov 01 '22 05:11

hus


1 Answers

Generally speaking you can connect different signals and concatenate operations as discussed in this page. You should have a look at it since it is full of nice and useful information.

However, when it comes to mouse events, an interesting approach to events concatenation is given by MouseEvents acceptation. Documentation says about MouseEvent::accepted:

Setting accepted to true prevents the mouse event from being propagated to items below this item. Generally, if the item acts on the mouse event then it should be accepted so that items lower in the stacking order do not also respond to the same event.

In this case we can take the opposite approach by not accepting the event. This way the pressed event can be used to both activate the drag and actually perform it. Then the MouseEvent can be accepted (implicitly) in the release event, occurring at the end of the drag.

Here is a simple example following this approach. As the mouse is pressed and hold the drag.target is set and drag can start, whereas when the mouse is released the drag.target is removed, removing the dragging behaviour. To test it, just press and hold the mouse over the rectangle and when it changes color just drag it.

import QtQuick 2.4
import QtQuick.Controls 1.3

ApplicationWindow {
    width: 300
    height: 300
    visible: true

    Rectangle {
        id: item
        border.width: 2
        x: 100
        y: 100
        width: 100
        height: 100
        state: "BASE"

        states: [
            State {
            name: "BASE"
            PropertyChanges { target: mouseArea; drag.target: undefined}
            PropertyChanges { target: item; color: "steelblue"}
        },
            State {
            name: "DRAGGABLE"
            PropertyChanges { target: mouseArea; drag.target: item}
            PropertyChanges { target: item; color: "darkblue"}
        }
        ]


        MouseArea {
            id: mouseArea
            anchors.fill: parent
            drag{
                // target:  NOT SET HERE
                minimumX: 0
                minimumY: 0
                maximumX: parent.parent.width - parent.width
                maximumY: parent.parent.height - parent.height
                smoothed: true
            }

            onPressAndHold: {
                item.state = "DRAGGABLE"
                mouse.accepted = false      // mouse event is USED but NOT CONSUMED...
            }

            onReleased: {
                item.state = "BASE"         // mouse event acceptation occurs here!
            }
        }
    }
}

This simple approach should work perfectly also with your custom signals.

like image 143
BaCaRoZzo Avatar answered Nov 16 '22 12:11

BaCaRoZzo