16

If I put a MouseArea on a QML element, then MouseArea will steal all mouse events. Thus, TextEdit will be uneditable and unselectable.

TextEdit {
    // some properties
    MouseArea {
        // some properties
        onClicked: { /* do something */ }
    }
}

Is there a way to solve it?

By the way, if I put a large MouseArea on another MouseArea, larger MouseArea will steal all mouse events. How do I solved it? I think passing on mouse events manually can solve that, but how to do it?

NG_
  • 6,895
  • 7
  • 45
  • 67
比尔盖子
  • 2,693
  • 5
  • 37
  • 53

4 Answers4

28

You have to enable the MouseArea to propagate the composed events like clicked or released to the underneath component, as described by @Torgeirl's answer.

If you want your TextEdit, Slider or CheckBox to receive these kind of events, simply pass through the event by setting its accepted property to false.

Sample code:

RowLayout {
    TextEdit { text: "Hi" }
    Slider {}
    CheckBox { text: "CheckBox"}

    MouseArea {
        anchors.fill: parent
        propagateComposedEvents: true

        onClicked: mouse.accepted = false;
        onPressed: mouse.accepted = false;
        onReleased: mouse.accepted = false;
        onDoubleClicked: mouse.accepted = false;
        onPositionChanged: mouse.accepted = false;
        onPressAndHold: mouse.accepted = false;
    }
}
BaCaRoZzo
  • 7,502
  • 6
  • 51
  • 82
szotsaki
  • 684
  • 7
  • 16
  • 6
    I was looking for a solution to something else when I came across this, and just thought I'd point out that there are some signal handlers for which setting `mouse.accepted = false` has no effect (search `MouseArea` docs for `has no effect` to find them all). – Mitch Jun 04 '15 at 14:20
  • 2
    This solution does not work if I want continuous updates on mouseX and mouseY. Change the TextEdit in the example code above to show the mouse X,Y location and you will see it stops updating whenever the mouse button is held down. Setting "mouse.accepted = false" in onPressed causes the MouseArea properties to not be updated until the button is released. Not sure if this is a bug? – Matt M Jan 26 '17 at 20:34
5

There is the property propagateComposedEvents which allows a MouseArea to let through mouse events such as clicked(). You have to set event.accepted = false in the event handler.

Please, see the documentation for MouseArea and the property propagateComposedEvents for more information and example.

Ivan Kush
  • 2,958
  • 2
  • 23
  • 39
Torgeirl
  • 51
  • 1
2

You can try something like this for your particular case:

Rectangle
{
   MouseArea 
   {
      id: mouseAreaTop
      anchors.fill: parent 
      OnClicked: { /* do something */ }
   }

   TextEdit 
   {
      /* Do whatever  */       
   }
}

Note that I have arranged these in an order. All children will have higher z than parent. Siblings coming later in the tree for a parent, have higher z values.

General idea is like this :

  1. Define all the mouse areas
  2. Arrange them on the z values

Read about z property here in the Qt documentation, you will be able to understand how to arrange the mouse areas.

eg:

Parent
{
    anchors.fill: parent
    child1
    {
        anchors.fill: parent
        z: 2
    }

    child2
    {
        anchors.fill: parent
        z: 1
    }

    child3
    {
        anchors.fill: parent
        z: 4
    }

    child4
    {
        anchors.fill: parent
        z: 3
    }
}

In this example i have overridden the natural ordering by assigning the z values myself.

Amit Tomar
  • 4,800
  • 6
  • 50
  • 83
  • No. That's isn't what I want. In your first example, mouseEvent will not emit because `TextEdit` is higher than `mouseArea`. I want `TextEdit` accept mouseEvent and selectable at the same time. I want to find a way to simulate Qt 5's`propagateComposedEvents` feature in Qt 4. – 比尔盖子 Apr 28 '13 at 04:32
0
                //消息框
                Rectangle {
                    id:msgRectangle
                    width: Math.min(messageText.implicitWidth +14, listView.width -98)
                    height: messageText.implicitHeight + 16
                    color:  send ? "#9dea6a" : "#eeeeee"
                    radius: 3
                    TextEdit {
                        id: messageText
                        text: content
                        wrapMode: TextEdit.Wrap
                        enabled: true
                        readOnly: true
                        selectByKeyboard: true
                        selectByMouse: true
                        selectedTextColor: "white"
                        persistentSelection:true
                        selectionColor: "#3396FF"

                    }
                    MouseArea{
                        id:text_area
                        width: parent.width
                        height: parent.height
                        acceptedButtons: Qt.LeftButton|Qt.RightButton
                        propagateComposedEvents: true
                        onClicked: {
                            if(mouse.button===Qt.LeftButton){
                                mouse.accepted = false;
                            } else {
                                mouse.accepted = true;
                            }

                        }
                        onPressed: {
                            if(mouse.button===Qt.LeftButton){
                                mouse.accepted = false;
                            } else {
                                mouse.accepted = true
                            }
                        }
                        onReleased:{
                            if(mouse.button===Qt.LeftButton){
                                mouse.accepted = false;
                            } else {
                                mouse.accepted = true
                            }
                        }
                        onDoubleClicked:{
                            if(mouse.button===Qt.LeftButton){
                                mouse.accepted = false;
                            } else {
                                mouse.accepted = true
                            }
                        }
                        onPositionChanged:{
                            if(mouse.button===Qt.LeftButton){
                                mouse.accepted = false;
                            } else {
                               mouse.accepted = true
                            }
                        }
                        onPressAndHold:{
                            if(mouse.button===Qt.LeftButton){
                                mouse.accepted = false;
                            } else {
                                mouse.accepted = true
                            }
                        }
                   }
                }