QML学习笔记(二十五)QML的KeyNavigation和FocusScope
前言
上一节中,我们学习了有关键盘按键的Keys属性,用于检测按键行为,但除此之外,还有一种叫KeyNavigation的属性,直接翻译过来叫键盘导航,我们可以用它来快速切换不同组件之间的当前焦点。另外,还有一个叫FocusScope的东西,它用于解决嵌套组件中子控件的焦点被抢的问题。
一、了解KeyNavigation
查阅帮助文档:
翻译一下描述:
基于按键的用户界面通常允许使用箭头键在可聚焦项目之间导航。KeyNavigation附加属性通过提供一种方便的方法来指定按下箭头或tab键时应获得焦点的项目,从而启用了此行为。
简单来说,就是通过箭头键来实现不同组件之间的聚焦切换。
我们新建一个项目测试一下吧。
二、KeyNavigation代码演示
这里直接用帮助文档里提供的代码,我们直接运行看看:
import QtQuick 2.14
import QtQuick.Window 2.14Window {visible: truewidth: 640height: 480title: qsTr("QmlKeyNavigation")Grid {width: 100; height: 100columns: 2Rectangle {id: topLeftwidth: 50; height: 50color: focus ? "red" : "lightgray"focus: trueKeyNavigation.right: topRightKeyNavigation.down: bottomLeft}Rectangle {id: topRightwidth: 50; height: 50color: focus ? "red" : "lightgray"KeyNavigation.left: topLeftKeyNavigation.down: bottomRight}Rectangle {id: bottomLeftwidth: 50; height: 50color: focus ? "red" : "lightgray"KeyNavigation.right: bottomRightKeyNavigation.up: topLeft}Rectangle {id: bottomRightwidth: 50; height: 50color: focus ? "red" : "lightgray"KeyNavigation.left: bottomLeftKeyNavigation.up: topRight}}
}
运行效果:
可以看到,当我们按上下左右的时候,当前焦点会在不同组件之间切换,以此激活不同的颜色。
至于实现方式也相当简洁,以左上角的矩形为例,当前焦点在它身上的时候,如果按键导航往右,给他设置到topRight也就是右上的矩形上;如果按键导航往下,给他设置到bottomLeft也就是左下的矩形上。
Rectangle {id: topLeftwidth: 50; height: 50color: focus ? "red" : "lightgray"focus: trueKeyNavigation.right: topRightKeyNavigation.down: bottomLeft}
除了上下左右外,还有tab和backtab(shift+tab)等形式,这点知道就行。
三、了解FocusScope
翻译描述:
在构建可重用的QML组件时,焦点范围有助于键盘焦点处理。所有细节都包含在键盘焦点文档中。
这样说感觉不够直观,我们看一个例子。
四、FocusScope代码演示
我们做一个自定义组件,叫CustomElement,它的代码如下:
import QtQuick 2.0Item {width: containerRectId.widthheight: containerRectId.heightproperty alias color: containerRectId.colorRectangle{id: containerRectIdwidth: 300height: 50color: "beige"focus: trueText {id: textIdanchors.centerIn: parenttext: "Default"}Keys.onPressed: function(event){if(event.key === Qt.Key_1){console.log("Pressed on key_1")textId.text = "Pressed on key_1"}else if(event.key === Qt.Key_2){console.log("Pressed on key_2")textId.text = "Pressed on key_2"}else{console.log("Pressed on another key: " + event.key)textId.text = "Pressed on another key: " + event.key}}}
}
它只是一个矩形,有文本输入和监听按键的相关信息打印,没什么特别的。这里给它设置了一个focus: true,这会导致问题。
main.qml中进行简单的应用。
Column{spacing: 20anchors.centerIn: parentCustomElement{color: "yellow"focus: true}CustomElement{color: "green"}}
运行后,问题现象就是:这里明明给第一个矩形设置了焦点,结果键盘按下的时候,触发的却第二个矩形的焦点。
事实上,这是一种相当混乱,且难以直观理解的现象。归根结底,是Item和Rectangle的嵌套时,焦点多层传递出现了问题。
这时,我们将Item改为FocusScope就能解决问题了。这样一来,设置焦点的时候就能正常传递到里面的实际组件,无需做其他的操作。
五、总结
本节扩展了KeyNavigation键盘导航和FocusScope焦点范围的知识,让我们能够更好地管理和控制键盘所产生的各种行为,对焦点这一常用的概念有较为清晰的开发认知。