如何在具有重叠鼠标区域的QML TableView中正确处理鼠标事件?

6
我已经将委托绑定到包含MouseAreaTableViewColumn。我使用MouseArea来检测表格中单元格的双击事件,这使我可以显示TextField以进行编辑。
问题在于委托MouseArea会阻止鼠标事件传播到TableView。这意味着TableView的选择行为不再起作用。具体而言,我启用了SelectionMode.ExtendedSelectionMouseArea子项很简单,最初是这样的:
MouseArea{
    id: mousearea
    anchors.fill: parent
    onDoubleClicked: {
        showTextField()
    }
}

在查询了文档后,看起来这应该可以工作:

MouseArea{
    id: mousearea
    anchors.fill: parent
    propagateComposedEvents: true        // new
    onDoubleClicked: {
        showTextField()
    }
    onPressed: mouse.accepted = false    // new
}

它确实可以,但现在我不能再捕获双击事件(在MouseArea中)了!这很有道理,因为文档后面指出:

pressed(MouseEvent mouse)

处理此信号时,请使用鼠标参数的accepted属性来控制此MouseArea是否处理按下和所有后续鼠标事件,直到释放。默认情况下接受事件并不允许其他位于其下方的MouseArea处理该事件。如果将accepted设置为false,则该MouseArea将不会收到更多事件,直到下次按下该按钮。

似乎没有办法在TableView级别上捕获单个单元格的鼠标事件。这是我第一天尝试使用QML,所以可能错过了一些明显的东西,但我的选择是什么?请注意,我正在使用PyQt。

MouseAreas 重叠在哪里,您希望每个 MouseArea 的行为是什么? - derM
抱歉,我已经编辑了我的答案并包含了更多的细节。请查看第二段。 - mohamedmoussa
你想要实现的唯一目标就是选择行吗? - derM
1个回答

6
如果你只是想实现选定文本,你可以手动设置选区: ```html

如果你只是想实现选定文本,你可以手动设置选区:

```
TableView {
    id: tv
    itemDelegate: Item {
        Text {
            anchors.centerIn: parent
            color: styleData.textColor
            elide: styleData.elideMode
            text: styleData.value
        }
        MouseArea {
            id: ma
            anchors.fill: parent
            onPressed: {
                tv.currentRow = styleData.row
                tv.selection.select(styleData.row) // <-- select here.
            }
            onClicked: {
                console.log(styleData.value)
            }
        }
    }

    TableViewColumn {
        role: 'c1'
        title: 'hey'
        width: 100
    }
    TableViewColumn {
        role: 'c2'
        title: 'tschau'
        width: 100
    }
    model: lm
}

目前我只进行选择操作。但是您可以编写自己的选择/取消选择逻辑。

您还可以从 TableView.__mouseArea 映射到委托。

import QtQuick 2.7
import QtQuick.Controls 1.4

ApplicationWindow {
    id: appWindow
    width: 1024
    height: 800
    visible: true

    ListModel {
        id: lm
        ListElement { c1: 'hallo1'; c2: 'bye' }
        ListElement { c1: 'hallo2'; c2: 'bye' }
        ListElement { c1: 'hallo3'; c2: 'bye' }
        ListElement { c1: 'hallo4'; c2: 'bye' }
        ListElement { c1: 'hallo5'; c2: 'bye' }
        ListElement { c1: 'hallo6'; c2: 'bye' }
        ListElement { c1: 'hallo7'; c2: 'bye' }
        ListElement { c1: 'hallo8'; c2: 'bye' }
        ListElement { c1: 'hallo9'; c2: 'bye' }
    }

    TableView {
        id: tv
        itemDelegate: Item {
            id: mydelegate
            signal doubleclicked()
            onDoubleclicked: console.log(styleData.value)
            Text {
                anchors.centerIn: parent
                color: styleData.textColor
                elide: styleData.elideMode
                text: styleData.value
            }

            Connections {
                target: tv.__mouseArea
                onDoubleClicked: {
                    // Map to the clickposition to the delegate
                    var pos = mydelegate.mapFromItem(tv.__mouseArea, mouse.x, mouse.y)
                    // Check whether the click was within the delegate
                    if (mydelegate.contains(pos)) mydelegate.doubleclicked()
                }
            }
        }

        TableViewColumn {
            role: 'c1'
            title: 'hey'
            width: 100
        }
        TableViewColumn {
            role: 'c2'
            title: 'tschau'
            width: 100
        }
        model: lm
    }
}

我原本希望不必重新实现TableView的选择逻辑。我认为可以将MouseArea的“pressed”信号连接到TableView以手动传播信号,但不幸的是,“pressed”也是一个属性名称(导致错误)。 - mohamedmoussa
其实,映射非常容易。我曾试图使用 childAt(x,y) 进行操作,但从未得到正确的子项。但如果我已经有了它,那就轻而易举了 :-) - derM

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