Input Elements

We have already used the MouseArea as a mouse input element. Next, we’ll focus on keyboard input. We start off with the text editing elements: TextInput and TextEdit.

TextInput

TextInput allows the user to enter a line of text. The element supports input constraints such as validator, inputMask, and echoMode.

  1. // textinput.qml
  2. import QtQuick
  3. Rectangle {
  4. width: 200
  5. height: 80
  6. color: "linen"
  7. TextInput {
  8. id: input1
  9. x: 8; y: 8
  10. width: 96; height: 20
  11. focus: true
  12. text: "Text Input 1"
  13. }
  14. TextInput {
  15. id: input2
  16. x: 8; y: 36
  17. width: 96; height: 20
  18. text: "Text Input 2"
  19. }
  20. }

Input Elements - 图1

The user can click inside a TextInput to change the focus. To support switching the focus by keyboard, we can use the KeyNavigation attached property.

  1. // textinput2.qml
  2. import QtQuick
  3. Rectangle {
  4. width: 200
  5. height: 80
  6. color: "linen"
  7. TextInput {
  8. id: input1
  9. x: 8; y: 8
  10. width: 96; height: 20
  11. focus: true
  12. text: "Text Input 1"
  13. KeyNavigation.tab: input2
  14. }
  15. TextInput {
  16. id: input2
  17. x: 8; y: 36
  18. width: 96; height: 20
  19. text: "Text Input 2"
  20. KeyNavigation.tab: input1
  21. }
  22. }

The KeyNavigation attached property supports a preset of navigation keys where an element id is bound to switch focus on the given key press.

A text input element comes with no visual presentation beside a blinking cursor and the entered text. For the user to be able to recognize the element as an input element it needs some visual decoration; for example, a simple rectangle. When placing the TextInput inside an element you need make sure you export the major properties you want others to be able to access.

We move this piece of code into our own component called TLineEditV1 for reuse.

  1. // TLineEditV1.qml
  2. import QtQuick
  3. Rectangle {
  4. width: 96; height: input.height + 8
  5. color: "lightsteelblue"
  6. border.color: "gray"
  7. property alias text: input.text
  8. property alias input: input
  9. TextInput {
  10. id: input
  11. anchors.fill: parent
  12. anchors.margins: 4
  13. focus: true
  14. }
  15. }

TIP

If you want to export the TextInput completely, you can export the element by using property alias input: input. The first input is the property name, where the 2nd input is the element id.

We then rewrite our KeyNavigation example with the new TLineEditV1 component.

  1. Rectangle {
  2. ...
  3. TLineEditV1 {
  4. id: input1
  5. ...
  6. }
  7. TLineEditV1 {
  8. id: input2
  9. ...
  10. }
  11. }

Input Elements - 图2

Try the tab key for navigation. You will experience the focus does not change to input2. The simple use of focus: true is not sufficient. The problem is that when the focus was transferred to the input2 element, the top-level item inside the TlineEditV1 (our Rectangle) received focus, and did not forward the focus to the TextInput. To prevent this, QML offers the FocusScope.

FocusScope

A focus scope declares that the last child element with focus: true receives the focus when the focus scope receives the focus. So it forwards the focus to the last focus-requesting child element. We will create a second version of our TLineEdit component called TLineEditV2, using a focus scope as the root element.

  1. // TLineEditV2.qml
  2. import QtQuick
  3. FocusScope {
  4. width: 96; height: input.height + 8
  5. Rectangle {
  6. anchors.fill: parent
  7. color: "lightsteelblue"
  8. border.color: "gray"
  9. }
  10. property alias text: input.text
  11. property alias input: input
  12. TextInput {
  13. id: input
  14. anchors.fill: parent
  15. anchors.margins: 4
  16. focus: true
  17. }
  18. }

Our example now looks like this:

  1. Rectangle {
  2. ...
  3. TLineEditV2 {
  4. id: input1
  5. ...
  6. }
  7. TLineEditV2 {
  8. id: input2
  9. ...
  10. }
  11. }

Pressing the tab key now successfully switches the focus between the 2 components and the correct child element inside the component is focused.

TextEdit

The TextEdit is very similar to TextInput, and supports a multi-line text edit field. It doesn’t have the text constraint properties, as this depends on querying the painted size of the text (paintedHeight, paintedWidth). We also create our own component called TTextEdit to provide an editing background and use the focus scope for better focus forwarding.

  1. // TTextEdit.qml
  2. import QtQuick
  3. FocusScope {
  4. width: 96; height: 96
  5. Rectangle {
  6. anchors.fill: parent
  7. color: "lightsteelblue"
  8. border.color: "gray"
  9. }
  10. property alias text: input.text
  11. property alias input: input
  12. TextEdit {
  13. id: input
  14. anchors.fill: parent
  15. anchors.margins: 4
  16. focus: true
  17. }
  18. }

You can use it like the TLineEdit component

  1. // textedit.qml
  2. import QtQuick
  3. Rectangle {
  4. width: 136
  5. height: 120
  6. color: "linen"
  7. TTextEdit {
  8. id: input
  9. x: 8; y: 8
  10. width: 120; height: 104
  11. focus: true
  12. text: "Text Edit"
  13. }
  14. }

Input Elements - 图3

Keys Element

The attached property Keys allows executing code based on certain key presses. For example, to move and scale a square, we can hook into the up, down, left and right keys to translate the element, and the plus and minus keys to scale the element.

  1. // keys.qml
  2. import QtQuick
  3. DarkSquare {
  4. width: 400; height: 200
  5. GreenSquare {
  6. id: square
  7. x: 8; y: 8
  8. }
  9. focus: true
  10. Keys.onLeftPressed: square.x -= 8
  11. Keys.onRightPressed: square.x += 8
  12. Keys.onUpPressed: square.y -= 8
  13. Keys.onDownPressed: square.y += 8
  14. Keys.onPressed: {
  15. switch(event.key) {
  16. case Qt.Key_Plus:
  17. square.scale += 0.2
  18. break;
  19. case Qt.Key_Minus:
  20. square.scale -= 0.2
  21. break;
  22. }
  23. }
  24. }

Input Elements - 图4