Problem with MouseArea in delegate



  • Hi everybody!

    I have a repeater which inserts rectangles in a GridLayout (see below), each rectangle holding a MouseArea. I want to catch the following mouse events:
    1.) The user clicks one of the rectangles and keeps the mouse button pressed.
    --> catch onPressed
    2.) The user moves the mouse around, still pressing the button
    --> catch onEntered from every rectangle the mouse pointer enters
    3.) The user releases the mouse button
    --> catch onReleased

    Somehow I am not able to implement this. If I set mouse.accepted = false in my onPressed-handler, I get the following onEntered-events, but never a onReleased. If I do mouse.accepted = true in onPressed, I get a final onRelaesed-event, but never a onEntered.
    I tried to put another MouseArea in front or behind the GridLayout, but nothing seems to work. Google was no help, either. Could anybody point me in the right direction?

    Thanks

    P.S.: My code:

    GridLayout {
        id: fieldGrid
        anchors.fill:parent
        //...
    
        Repeater {
            id: repeater
            model: game.board
    
            // My delegate
            Rectangle {
                id: del
                // coord comes from model
                Layout.column: coord.x
                Layout.row: coord.y
                Layout.fillWidth: true
                Layout.fillHeight: true
                //...
    
                MouseArea {
                    id: delMouseArea
                    anchors.fill: parent
                    acceptedButtons: Qt.LeftButton
                    hoverEnabled: true
    
                    onPressed: {
                        console.log("onPressed")
                        mouse.accepted = false;
                    }
                    onReleased: {
                        console.log("onReleased")
                    }
                    onEntered: {
                        console.log("onEntered")
                    }
                }
            }
        }
    }
    
    

  • Moderators

    Hi @nnnnn and Welcome,
    Putting GridLayout inside MouseArea should work. In that case add onReleased event handler for that MouseArea. Now once this event is triggered you just have to find the child of GridLayout under that mouse location. Like this:

    MouseArea {
        anchors.fill:parent
        onReleased: console.log(fieldGrid.childAt(mouseX,mouseY).objectName)
        GridLayout {
            id: fieldGrid
            ...
            ...
    

    This will print the object name of the Rectangle under that mouse location.

    The problem why we need to do this is because that event do not work if area moves under the mouse.



  • @nnnnn

    This is also working for me:

                GridView {
                    id: grid
                    clip:true
                    anchors.fill: parent
                    cellWidth: Units.dp(80)
                    cellHeight: Units.dp(80)
                    interactive: false
    
                    delegate: Rectangle {
                        id: rect
                        width: grid.cellWidth - Units.dp(5)
                        height: grid.cellHeight - Units.dp(5)
                        color: backcolor
    
                        MouseArea {
                            hoverEnabled: true
                            anchors.fill: parent
                            onPressed: {
                                console.log("pressed")
                            }
                            onReleased: {
                                console.log("released")
                            }
                            onEntered: {
                                console.log("entered");
                            }
                        }
                 }
    
    
                    Component.onCompleted: {
                        for(var i=0;i<36;i++) {
                            grid.model.append({backcolor: "#E0E0E0"});
                        }
                    }
    
                    model: ListModel {
    
                    }
       }


  • @p3c0

    Thanks for your answer!

    Unfortunately, this did not solve my problem. With an additional MouseArea (as parent of the GridLayout) I can capture the Released-events (form the outer MouseArea), the Pressed-event (from the inner MouseAreas), however I do not see any Entered-events anymore :-(


  • Moderators

    @nnnnn That's strange. Is there any other component present apart from the code that you posted earlier ?



  • @sk2212

    I tried your example here - I do not get entered-Events when I move the mouse pointer around while the button is pressed; same problem as in my code.

    Once again my scenario - to avoid misunderstandings:
    Go to a cell, press the button, keep button pressed, move the pointer to other cells, release the button.
    In this case, I would like a pressed-event from the first cell, entered-events from all others, and a released-event from the last one. Seems to be tricky...

    Cheers



  • @p3c0

    Hi!

    Here is a complete example (which is unfortunately not doing what I want). Anything wrong here?

    import QtQuick 2.4
    import QtQuick.Window 2.2
    import QtQuick.Layouts 1.1
    
    Window {
        visible: true
        color: "black"
    
        MouseArea {
            id: outer
            anchors.fill: parent
    
            onReleased: {
                console.log("outer - onReleased")
            }
    
            GridLayout {
                id: fieldGrid
                anchors.fill:parent
                rows: 2
                columns: 2
    
                Repeater {
                    id: repeater
                    model: myModel
    
                    Rectangle {
                        id: del
                        Layout.column: col
                        Layout.row: row
                        Layout.fillWidth: true
                        Layout.fillHeight: true
    
                        Text {
                            anchors.centerIn: parent
                            text: name
                        }
    
                        MouseArea {
                            id: inner
                            anchors.fill: parent
                            hoverEnabled: true
    
                            onPressed: {
                                console.log("inner - onPressed")
                                mouse.accepted = false;
                            }
                            onEntered: {
                                console.log("inner - onEntered")
                            }
                        }
                    }
                }
            }
        }
    
        ListModel {
            id: myModel
    
            ListElement { row: 0; col: 0; name: "a"}
            ListElement { row: 0; col: 1; name: "b"}
            ListElement { row: 1; col: 0; name: "c"}
            ListElement { row: 1; col: 1; name: "d"}
        }
    }
    
    

  • Moderators

    @nnnnn This too works on my system. I'm using Qt 5.5 on Ubuntu.



  • Really? You get Entered-events while you keep the mouse button pressed?

    Ok, I will check with Qt 5.5 here, I wanted to update anyway. Thanks for your help, I will post how things are going...



  • Hmm, it's not working for me under Qt5.5/Kubuntu 14.04 either. No entered-Events when I move the mouse around while pressing the mouse button.



  • @nnnnn

    Ah...got your point. The events are not triggered when you press a button, hold this button and move to another button. THAN the events for the "new" entered button are not triggered.

    I did not know a solution so far...



  • I really find no solution for this using MouseArea. My only hope now is that I can find a workaround using a MultiPointTouchArea, but maybe this is something completely different (have to check to documentation first...)



  • I have a simple solution now, using only one MouseArea on top and looking for onPositionChanged. I don't think it is very beautifuly (I have to call childAt() all the time), but at least it is working.

    import QtQuick 2.4
    import QtQuick.Window 2.2
    import QtQuick.Layouts 1.1
    
    Window {
        visible: true
        color: "black"
    
        GridLayout {
            id: fieldGrid
            anchors.fill: parent
            rows: 2
            columns: 2
    
            Repeater {
                id: repeater
                model: myModel
    
                Rectangle {
                    id: del
                    Layout.column: col
                    Layout.row: row
                    Layout.fillWidth: true
                    Layout.fillHeight: true
    
                    Text {
                        anchors.centerIn: parent
                        text: name
                    }
                }
            }
        }
    
        MouseArea {
            anchors.fill: parent
            property point pos: Qt.point(-1, -1)
    
            onPressed: {
                var obj = fieldGrid.childAt(mouse.x, mouse.y)
                if ( !obj )
                    return;
    
                console.log("onPressed")
                pos = Qt.point(obj.Layout.row, obj.Layout.column)
                console.log("newField: " +  pos)
            }
            onReleased: {
                console.log("onReleased")
            }
    
            onPositionChanged: {
                var obj = fieldGrid.childAt(mouse.x, mouse.y)
                if ( !obj )
                    return;
    
                var newPos = Qt.point(obj.Layout.row, obj.Layout.column)
                if ( newPos === pos )
                    return;
    
                console.log("newField: " +  newPos)
                pos = newPos;
            }
        }
    
        ListModel {
            id: myModel
    
            ListElement {row: 0; col: 0; name: "a" }
            ListElement {row: 0; col: 1; name: "b" }
            ListElement {row: 1; col: 0; name: "c" }
            ListElement {row: 1; col: 1; name: "d" }
        }
    }
    
    

  • Moderators

    @nnnnn Hmm. I overlooked your onEntered requirement. It doesnot work in my example. The problem is that once you set mouse.accepted=false the release event is not trapped.


Log in to reply
 

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