点击QML GridView项外部的事件在Qt6中如何获取?

huangapple go评论64阅读模式
英文:

How to get the event of clicking outside of QML GridView items in Qt6?

问题

在Qt6中,您应该使用PropagationPhase属性来处理这个问题。以下是相应的修改代码:

import QtQuick
import QtQuick.Controls

ApplicationWindow {
    id: root
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    ListModel {
        id: listModel
        ListElement {
            name: "Jim Williams"
        }
        ListElement {
            name: "John Brown"
        }
        ListElement {
            name: "Bill Smyth"
        }
        ListElement {
            name: "Sam Wise"
        }
    }

    GridView {
        id: gridView
        anchors.fill: parent
        cellWidth: 80
        cellHeight: 80
        model: listModel

        delegate: Item {
            id: wrapper
            width: gridView.cellWidth
            height: gridView.cellHeight

            Rectangle {
                anchors.fill: parent
                anchors.margins: 4
                color: wrapper.GridView.isCurrentItem ? "#009688" : "#3d3d3d"

                Text {
                    anchors.fill: parent
                    color: "white"
                    text: name
                }
            }

            MouseArea {
                anchors.fill: parent
                onClicked: {
                    gridView.currentIndex = index
                }
            }
        }

        MouseArea {
            anchors.fill: parent
            propagateComposedEvents: true
            onClicked: {
                if (!gridView.isCurrentItem) {
                    console.log("out clicked!")
                    gridView.currentIndex = -1
                }
            }
        }
    }
}

这个修改将在Qt6中处理点击事件的传播,以达到取消当前选择的效果。

英文:

I want to implement deselecting the current selection by clicking outside of the GridView items.
The following code works fine in Qt5. However,the click event cannot be obtained in Qt6.

import QtQuick
import QtQuick.Controls
ApplicationWindow {
id: root
width: 640
height: 480
visible: true
title: qsTr("Hello World")
ListModel {
id: listModel
ListElement {
name: "Jim Williams"
}
ListElement {
name: "John Brown"
}
ListElement {
name: "Bill Smyth"
}
ListElement {
name: "Sam Wise"
}
}
GridView {
id: gridView
anchors.fill: parent
cellWidth: 80
cellHeight: 80
model: listModel
MouseArea {
z: -1
anchors.fill: parent
onClicked: {
console.log("out clicked!")
gridView.currentIndex = -1
}
}
delegate: Item {
id: wrapper
width: gridView.cellWidth
height: gridView.cellHeight
Rectangle {
anchors.fill: parent
anchors.margins: 4
color: wrapper.GridView.isCurrentItem ? "#009688" :"#3d3d3d"
Text {
anchors.fill: parent
color: "white"
text: name
}
}
MouseArea {
anchors.fill: parent
onClicked: {
gridView.currentIndex = index
}
}
}
}
}

In Qt5, I set the z of the first MouseArea to -1, which can achieve the effect I want. But this method is invalid in Qt6 and cannot respond to the clicked event of the first MouseArea.
What should I do in Qt6?

答案1

得分: 1

以下是您要翻译的代码部分:

这是一个奇怪的地方,TapHandlerMouseArea 更适用。通过在您的 GridView 内定义一个 TapHandler,您将在与您的 GridView 中的区域交互时收到通知,但不是在任何您的 delegates 上。我还将 MouseArea 移动到您的 Rectangle 内部,以便即使在 delegates 之间的白边上也能点击到 TapHandler

import QtQuick
import QtQuick.Controls
Page {
    ListModel {
        id: listModel
        ListElement { name: "Jim Williams" }
        ListElement { name: "John Brown" }
        ListElement { name: "Bill Smyth" }
        ListElement { name: "Sam Wise" }
    }
    
    GridView {
        id: gridView
        anchors.fill: parent
        cellWidth: 80
        cellHeight: 80
        model: listModel
        TapHandler {
            onTapped: {
                console.log("out clicked!")
                gridView.currentIndex = -1
            }
        }
        delegate: Item {
            id: wrapper
            width: gridView.cellWidth
            height: gridView.cellHeight
            Rectangle {
                anchors.fill: parent
                anchors.margins: 4
                color: wrapper.GridView.isCurrentItem ? "#009688" : "#3d3d3d"
                Text {
                    anchors.fill: parent
                    color: "white"
                    text: name
                }
                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        gridView.currentIndex = index
                    }
                }
            }
        }
    }
}

您可以在线试用!

英文:

This is one of the weird places where TapHandler works better than MouseArea. By defining a TapHandler inside your GridView you will be notified when you are interacting in an area that's in your GridView but not on any of your delegates. I also move the MouseArea to inside your Rectangle so even the white edges between the delegates is now clicking thru to the TapHandler.

import QtQuick
import QtQuick.Controls
Page {
    ListModel {
        id: listModel
        ListElement { name: "Jim Williams" }
        ListElement { name: "John Brown" }
        ListElement { name: "Bill Smyth" }
        ListElement { name: "Sam Wise" }
    }
    
    GridView {
        id: gridView
        anchors.fill: parent
        cellWidth: 80
        cellHeight: 80
        model: listModel
        TapHandler {
            onTapped: {
                console.log("out clicked!")
                gridView.currentIndex = -1
            }
        }
        delegate: Item {
            id: wrapper
            width: gridView.cellWidth
            height: gridView.cellHeight
            Rectangle {
                anchors.fill: parent
                anchors.margins: 4
                color: wrapper.GridView.isCurrentItem ? "#009688" :"#3d3d3d"
                Text {
                    anchors.fill: parent
                    color: "white"
                    text: name
                }
                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        gridView.currentIndex = index
                    }
                }
            }
        }
    }
}

You can Try it Online!

答案2

得分: 0

以下是代码的中文翻译:

// 在 GridView 中,你可以仅使用鼠标处理程序并在那里处理选择。首先将鼠标位置映射到 GridView 坐标系统,然后查找该位置的索引。

GridView {
    id: gridView
    anchors.fill: parent
    cellWidth: 80
    cellHeight: 80

    model: listModel

    MouseArea {
        anchors.fill: parent
        onClicked: (mouse) => {
            console.log("grid clicked!");

            let posInGridView = Qt.point(mouse.x, mouse.y);
            let posInContentItem = mapToItem(gridView.contentItem, posInGridView);
            let index = gridView.indexAt(posInContentItem.x, posInContentItem.y);

            gridView.currentIndex = index;
        }
    }

    delegate: Item {
        id: wrapper
        width: gridView.cellWidth
        height: gridView.cellHeight

        Rectangle {
            anchors.fill: parent
            anchors.margins: 4
            color: wrapper.GridView.isCurrentItem ? "#009688" : "#3d3d3d"

            Text {
                anchors.fill: parent
                color: "white"
                text: name
            }
        }
    }
}

请注意,代码中的注释已被翻译成中文。

英文:

You can use just on mouse handler in the GridView and handle selections there. First you map the mouse position to the GridView coordinate system. Then you lookup the index at this position.

GridView {
id: gridView
anchors.fill: parent
cellWidth: 80
cellHeight: 80
model: listModel
MouseArea {
anchors.fill: parent
onClicked: (mouse) => {
console.log("grid clicked!");
let posInGridView = Qt.point(mouse.x, mouse.y)
let posInContentItem = mapToItem(gridView.contentItem, posInGridView)
let index = gridView.indexAt(posInContentItem.x, posInContentItem.y)
gridView.currentIndex = index;
}
}
delegate: Item {
id: wrapper
width: gridView.cellWidth
height: gridView.cellHeight
Rectangle {
anchors.fill: parent
anchors.margins: 4
color: wrapper.GridView.isCurrentItem ? "#009688" :"#3d3d3d"
Text {
anchors.fill: parent
color: "white"
text: name
}
}
}
}

huangapple
  • 本文由 发表于 2023年3月23日 10:54:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75818900.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定