# 输入元素
我们早已使用鼠标输入元素 MouseArea,接下来看看键盘输入。我们从文本编辑元素 TextInput 和 TextEdit 元素开始。
# TextInput
TextInput 允许用户输入一行文本。该元素支持输入约束,如 validator,inputMask 和 echoMode。
// textinput.qml
import QtQuick
Rectangle {
width: 200
height: 80
color: "linen"
TextInput {
id: input1
x: 8; y: 8
width: 96; height: 20
focus: true
text: "Text Input 1"
}
TextInput {
id: input2
x: 8; y: 36
width: 96; height: 20
text: "Text Input 2"
}
}
用户可点击 TextInput 内部获得焦点。要支持通过键盘切换焦点,可以使用附加属性 KeyNavigation。
// textinput2.qml
import QtQuick
Rectangle {
width: 200
height: 80
color: "linen"
TextInput {
id: input1
x: 8; y: 8
width: 96; height: 20
focus: true
text: "Text Input 1"
KeyNavigation.tab: input2
}
TextInput {
id: input2
x: 8; y: 36
width: 96; height: 20
text: "Text Input 2"
KeyNavigation.tab: input1
}
}
附加属性 KeyNavigation 支持一些预设的导航键,按下导航键,可以在元素间切换焦点。
文本输入元素除了闪烁的光标和输入的文本外没有任何视觉展示。为了让用户能将元素识别为输入元素,需要一些视觉装饰,例如,简单的矩形。若将 TextInput 放入其它元素,需要确保导出了要使用的主要元素。
为了复用,我们将这段代码移入了自定义组件 TLineEditV1。
// TLineEditV1.qml
import QtQuick
Rectangle {
width: 96; height: input.height + 8
color: "lightsteelblue"
border.color: "gray"
property alias text: input.text
property alias input: input
TextInput {
id: input
anchors.fill: parent
anchors.margins: 4
focus: true
}
}
提示
若你想完全导出 TextInput,可以通过 property alias input: input 完成。第一个 input 是属性名称,第二个是元素名称。
随后我们用 TLineEditV1 组件重写了 KeyNavigation 实例。
Rectangle {
...
TLineEditV1 {
id: input1
...
}
TLineEditV1 {
id: input2
...
}
}
尝试按下 tab 键触发导航。你会发现焦点并未切换至 input2。只配置 focus: true 是不够的。问题是当焦点切给 input2 元素时,TlineEditV1 内的顶级元素(Rectangle)获得了焦点,并未将焦点转发给 TextInput。为了避免此问题,QML 提供了 FocusScope。
# FocusScope
焦点作用域内最后一个 focus: true 的子元素会获得焦点。所以它将焦点转发给最后一个请求焦点的子元素。我们会用焦点作用域创建第二版的 TLineEdit 组件,名为 TLineEditV2。
// TLineEditV2.qml
import QtQuick
FocusScope {
width: 96; height: input.height + 8
Rectangle {
anchors.fill: parent
color: "lightsteelblue"
border.color: "gray"
}
property alias text: input.text
property alias input: input
TextInput {
id: input
anchors.fill: parent
anchors.margins: 4
focus: true
}
}
我们的实例现在长这样:
Rectangle {
...
TLineEditV2 {
id: input1
...
}
TLineEditV2 {
id: input2
...
}
}
现在按下 tab 键,能成功地在两个组件间正确切换,内部的子元素也能正确的获得焦点。
# TextEdit
TextEdit 与 TextInput 十分类似,支持多行文本。它没有文本约束属性,因为着依赖于查询文本内容尺寸(contentHeight,contentWidth)。我们也创建了名为 TTextEdit 的自定义组件,为编辑区域提供了背景色,使用了焦点作用域获得更好的焦点转发机制。
// TTextEdit.qml
import QtQuick
FocusScope {
width: 96; height: 96
Rectangle {
anchors.fill: parent
color: "lightsteelblue"
border.color: "gray"
}
property alias text: input.text
property alias input: input
TextEdit {
id: input
anchors.fill: parent
anchors.margins: 4
focus: true
}
}
你可以像使用 TLineEdit 组件一样使用它
// textedit.qml
import QtQuick
Rectangle {
width: 136
height: 120
color: "linen"
TTextEdit {
id: input
x: 8; y: 8
width: 120; height: 104
focus: true
text: "Text Edit"
}
}
# Keys 元素
附加属性 Keys 允许在按下某个按键时执行代码。例如,为了移动,缩小或放大矩形,我们可以钩入上,下,左和右键,在按下这些键时变化元素,也可以钩入加和减键,在按下这些键时执行缩放元素操作。
// keys.qml
import QtQuick
DarkSquare {
width: 400; height: 200
GreenSquare {
id: square
x: 8; y: 8
}
focus: true
Keys.onLeftPressed: square.x -= 8
Keys.onRightPressed: square.x += 8
Keys.onUpPressed: square.y -= 8
Keys.onDownPressed: square.y += 8
Keys.onPressed: function (event) {
switch(event.key) {
case Qt.Key_Plus:
square.scale += 0.2
break;
case Qt.Key_Minus:
square.scale -= 0.2
break;
}
}
}