英文:
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
以下是您要翻译的代码部分:
这是一个奇怪的地方,TapHandler
比 MouseArea
更适用。通过在您的 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
}
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论