MouseArea偷走了QML元素的鼠标事件

16

如果我在 QML 元素上放置一个 MouseArea,那么 MouseArea 将会抢占所有的鼠标事件。因此,TextEdit 将无法编辑和选中。

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

有没有解决的方法?

顺便说一下,如果我在另一个MouseArea上放置了一个较大的MouseArea,那么较大的MouseArea将夺取所有鼠标事件。如何解决这个问题?我认为手动传递鼠标事件可以解决这个问题,但该怎么做呢?

4个回答

28

您需要启用MouseArea来传播像clickedreleased这样的组合事件到下面的组件中,正如@Torgeirl的答案所描述的那样。

如果您希望您的TextEditSliderCheckBox接收此类事件,只需通过将其accepted属性设置为false 来传递事件即可。

示例代码:

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;
    }
}

6
当我在寻找另一个问题的解决方案时,偶然发现了这个,并想指出有些信号处理程序不受mouse.accepted = false设置影响(搜索MouseArea文档中的has no effect可以找到所有相关内容)。 - Mitch
2
这个解决方案无法实现对鼠标X和Y坐标的连续更新。将上面示例代码中的TextEdit更改为显示鼠标X、Y位置,你会发现它在按住鼠标按钮时停止更新。在onPressed中设置“mouse.accepted = false”会导致MouseArea属性直到释放按钮才被更新。不确定这是否是一个错误? - Matt M

5

有一个属性propagateComposedEvents,它允许MouseArea通过鼠标事件(如clicked())。

您需要在事件处理程序中设置event.accepted = false

请查看MouseArea和属性propagateComposedEvents的文档以获取更多信息和示例。


我使用Qt4。我无法使用它。 - 比尔盖子

2
您可以尝试以下方法来解决您的问题:
Rectangle
{
   MouseArea 
   {
      id: mouseAreaTop
      anchors.fill: parent 
      OnClicked: { /* do something */ }
   }

   TextEdit 
   {
      /* Do whatever  */       
   }
}

请注意,我已经按照一个“顺序”进行了安排。所有子元素将具有比父元素更高的z值。对于父元素而言,在树形结构中后出现的兄弟将具有较高的z值。
一般思路如下:
  1. 定义所有鼠标区域
  2. 将它们按照z值排列
在Qt文档的这里阅读有关z属性的内容,您将能够理解如何排列鼠标区域。
例如:
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
    }
}

在这个例子中,我通过手动分配z值来覆盖自然排序。

不,那不是我想要的。在你的第一个示例中,由于“TextEdit”比“mouseArea”更高,所以mouseEvent 不会被发射。我想让“TextEdit”既能接受mouseEvent,又能同时可选择。我想找到一种在Qt 4中模拟Qt 5的“propagateComposedEvents”功能的方法。 - 比尔盖子

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
                            }
                        }
                   }
                }

这个问题已经被 BaCaRoZzo 和 szotsaki 的方法解决了,非常感谢。 - 李玉峰

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接