QML:Gridview 键盘导航不工作
QML: Gridview keyboard navigation not working
我正在使用 gridview 来显示从 c++ 端生成的复杂数据模型。除了 gridview 不接受或响应任何 keyNavigation 事件外,我一切正常。这是我的代码
GridView{
id: gridView
anchors.fill: parent
clip: true
cellWidth: 315
cellHeight: 300/6+15
focus: true
model: system.DataList
highlightFollowsCurrentItem: true
keyNavigationEnabled: true//enabled but still doesnt work
//keyNavigationWraps: true//does this matter
highlight: Rectangle{
color: highlightColor
radius: 5
width: gridView.cellWidth
height: gridView.cellHeight
x: gridView.currentItem.x
y: gridView.currentItem.y
Behavior on x { SpringAnimation { spring: 3; damping: 0.2 } }
Behavior on y { SpringAnimation { spring: 3; damping: 0.2 } }
}
delegate: Component{
Rectangle{
id: viewParentRect
width: gridView.cellWidth;
height: diskListView.cellHeight - 15
color: "transparent"
Row{
anchors.fill: parent
Rectangle{
width: parent.width/6 ; height: parent.height
color: "transparent"
Image {
id: image
anchors.centerIn: parent
source: model.modelData.IconPath
sourceSize.width: parent.width
sourceSize.height: parent.height
}
}
Column{
Text {
id: displayName
text: model.modelData.DisplayName
font.family: "Sans Serif"
font.pointSize: viewParentRect.width/30
}
Text {
id: usageText
text: model.modelData.Usage
font.family: "Sans Serif"
font.pointSize: viewParentRect.width/30
}
}
}
MouseArea{
anchors.fill: parent
onClicked: {
gridView.currentIndex = index
}
onDoubleClicked: {
system.enter(model.modelData.Path)
}
}
}
}
}
我尝试在某些点保留断点,结果是根本没有触发任何按键事件。上面的代码在鼠标上运行良好,但由于我是为桌面开发的,所以我需要键盘导航才能正常工作(即使鼠标导航不起作用,也不是问题)。
好吧,QML 本身为 GridView 和 ListView 提供了 keyNavigation,只要它的焦点 属性 设置为 true 并且还有用户焦点。如果其他组件是在之后创建的,焦点可能会被其他组件占用,这就是为什么按键导航无法按预期工作的原因。
在我的例子中,我创建了两个 Component/s,其中两个都有两个不同的 GridView,然后使用 StackView 将其作为父级,这从两个 GridView 中窃取了焦点。
我的第一个解决方法是通过 StackView 检测按键,如果它们是箭头键 and/or enter/return 键,则将它们传递给 GridView。将 GridView keyNavigationEnabled 属性 设置为 false 并手动处理这些事件。这种方法非常有效,但代码变得太复杂了。所以我写了第二种方法。
动态创建两个组件并在 StackView 中只保留一个组件。带有 FocusScope 的父 GridView(以及其他需要独占焦点的项目)并通过父组件检测焦点并将它们转移到子组件。最后,让 QML 处理所有关键导航。这是代码,
main.qrc
StackView{
id: stackWindow
width: mainWindow.width
height: mainWindow.height
focus: true
Component.onCompleted: {push(Qt.createComponent("qrc:/PrimaryHomePage.qml"))}
onCurrentItemChanged: {currentItem.forceActiveFocus()}
Connections{
target: rSystem
ignoreUnknownSignals: true
onSwitchBetweenViews: {
if(newValue === 1){
stackWindow.pop()
stackWindow.push(Qt.createComponent("qrc:/SecondaryViewPage.qml"))
}
else if(newValue === 0){
stackWindow.pop()
stackWindow.push(Qt.createComponent("qrc:/PrimaryHomePage.qml"))
}
}
}
}
先出栈确保StackView在一个item中只拥有一个item(也可以使用replace)。
PrimaryHomePage.qrc
Item {
id: primaryHomePageParentItem
width: parent.width
height: parent.height
FocusScope{
id: focusScope
anchors.fill: parent
rGridView{
id: GridView_local
availablewidth: parent.width
}
}
onFocusChanged: {focusScope.focus = true}
}
还好,它比第一种方法更快。
我正在使用 gridview 来显示从 c++ 端生成的复杂数据模型。除了 gridview 不接受或响应任何 keyNavigation 事件外,我一切正常。这是我的代码
GridView{
id: gridView
anchors.fill: parent
clip: true
cellWidth: 315
cellHeight: 300/6+15
focus: true
model: system.DataList
highlightFollowsCurrentItem: true
keyNavigationEnabled: true//enabled but still doesnt work
//keyNavigationWraps: true//does this matter
highlight: Rectangle{
color: highlightColor
radius: 5
width: gridView.cellWidth
height: gridView.cellHeight
x: gridView.currentItem.x
y: gridView.currentItem.y
Behavior on x { SpringAnimation { spring: 3; damping: 0.2 } }
Behavior on y { SpringAnimation { spring: 3; damping: 0.2 } }
}
delegate: Component{
Rectangle{
id: viewParentRect
width: gridView.cellWidth;
height: diskListView.cellHeight - 15
color: "transparent"
Row{
anchors.fill: parent
Rectangle{
width: parent.width/6 ; height: parent.height
color: "transparent"
Image {
id: image
anchors.centerIn: parent
source: model.modelData.IconPath
sourceSize.width: parent.width
sourceSize.height: parent.height
}
}
Column{
Text {
id: displayName
text: model.modelData.DisplayName
font.family: "Sans Serif"
font.pointSize: viewParentRect.width/30
}
Text {
id: usageText
text: model.modelData.Usage
font.family: "Sans Serif"
font.pointSize: viewParentRect.width/30
}
}
}
MouseArea{
anchors.fill: parent
onClicked: {
gridView.currentIndex = index
}
onDoubleClicked: {
system.enter(model.modelData.Path)
}
}
}
}
}
我尝试在某些点保留断点,结果是根本没有触发任何按键事件。上面的代码在鼠标上运行良好,但由于我是为桌面开发的,所以我需要键盘导航才能正常工作(即使鼠标导航不起作用,也不是问题)。
好吧,QML 本身为 GridView 和 ListView 提供了 keyNavigation,只要它的焦点 属性 设置为 true 并且还有用户焦点。如果其他组件是在之后创建的,焦点可能会被其他组件占用,这就是为什么按键导航无法按预期工作的原因。
在我的例子中,我创建了两个 Component/s,其中两个都有两个不同的 GridView,然后使用 StackView 将其作为父级,这从两个 GridView 中窃取了焦点。
我的第一个解决方法是通过 StackView 检测按键,如果它们是箭头键 and/or enter/return 键,则将它们传递给 GridView。将 GridView keyNavigationEnabled 属性 设置为 false 并手动处理这些事件。这种方法非常有效,但代码变得太复杂了。所以我写了第二种方法。
动态创建两个组件并在 StackView 中只保留一个组件。带有 FocusScope 的父 GridView(以及其他需要独占焦点的项目)并通过父组件检测焦点并将它们转移到子组件。最后,让 QML 处理所有关键导航。这是代码,
main.qrc
StackView{
id: stackWindow
width: mainWindow.width
height: mainWindow.height
focus: true
Component.onCompleted: {push(Qt.createComponent("qrc:/PrimaryHomePage.qml"))}
onCurrentItemChanged: {currentItem.forceActiveFocus()}
Connections{
target: rSystem
ignoreUnknownSignals: true
onSwitchBetweenViews: {
if(newValue === 1){
stackWindow.pop()
stackWindow.push(Qt.createComponent("qrc:/SecondaryViewPage.qml"))
}
else if(newValue === 0){
stackWindow.pop()
stackWindow.push(Qt.createComponent("qrc:/PrimaryHomePage.qml"))
}
}
}
}
先出栈确保StackView在一个item中只拥有一个item(也可以使用replace)。
PrimaryHomePage.qrc
Item {
id: primaryHomePageParentItem
width: parent.width
height: parent.height
FocusScope{
id: focusScope
anchors.fill: parent
rGridView{
id: GridView_local
availablewidth: parent.width
}
}
onFocusChanged: {focusScope.focus = true}
}
还好,它比第一种方法更快。