This chapter will reveal the hidden mechanics of user input in QML. Here you’ll discover how mouse, keyboard, and multitouch follow the same logic, learn the secret of proper selection between signals and properties, and we’ll reveal how to avoid typical focus and event pitfalls. The result — more predictable interface behavior and noticeably fewer bugs even at the prototype stage.
MouseArea will be covered, custom signals, focus management through KeyNavigation, “raw” input through Keys, and working with MultiPointTouchArea. In practice, this allows reducing handler code by orders of magnitude and achieving interface response faster than with the classical approach.
Skipping this chapter means continuing to fix symptoms instead of the cause.
This chapter includes ready-to-use code examples.
Chapter Self-Check
Why does the TextInput element need to have width explicitly set through the width property, even if the text is empty?Answer
Correct answer: If TextInput contains no text, its width becomes 0, making it impossible to click on the element to get focus. Explicit width setting guarantees the ability to interact even with an empty field.
What’s the fundamental difference between using the clicked signal and the clicked property for a button?Answer
Correct answer: A signal transmits an event in one direction and the receiver cannot change the sender’s state; a property allows two-way binding and value changes. The handler for a property is called onClickedChanged, and for a signal — onClicked.
Why is the acceptedButtons parameter used in MouseArea?Answer
Correct answer: It limits handler triggering to only specific mouse buttons (for example, only left and right), preventing reaction to unwanted events from other buttons.
What will happen if you don’t set hoverEnabled: true for MouseArea when using onEntered/onExited?Answer
Correct answer: The onEntered and onExited handlers won’t trigger, because by default MouseArea doesn’t track cursor hover events and only reacts to clicks.
Why in the button example are the BorderImage dimensions increased by 15 pixels relative to the text dimensions?Answer
Correct answer: This creates internal padding around the text, ensuring a visually appealing button appearance where text doesn’t stick to the edges.
When is it more appropriate to use signals instead of properties for interaction between elements?Answer
Correct answer: Signals are preferable for interaction between autonomous, independent elements where no feedback is required. Properties are better suited for binding elements within a single parent container.
How does the automatic handler generation mechanism work for custom signals?Answer
Correct answer: When declaring a signal through the signal keyword, a handler is automatically created with the “on” prefix and the signal name with a capital letter (for example, for signal mousePositionChanged, onMousePositionChanged is created).
What will happen if you define more TouchPoint elements in MultiPointTouchArea than specified in maximumTouchPoints?Answer
Correct answer: Extra TouchPoints won’t be activated, since maximumTouchPoints limits the number of simultaneously processed touches. Only the first N touches will be processed according to the specified limit.
Why use the attached property KeyNavigation.tab instead of simple focus change in the Keys.onPressed handler?Answer
Correct answer: KeyNavigation.tab provides a declarative way to describe navigation, making code more readable and simplifying focus management without the need to write imperative event handling logic.
In what cases should you use Keys.forwardTo and what elements can be passed there?Answer
Correct answer: Keys.forwardTo is used to forward keyboard events to other elements for further processing. You can pass both individual elements and lists of objects.
Why is the TouchPoint element compared to MouseArea?Answer
Correct answer: TouchPoint is functionally analogous to MouseArea, but for touch input — each TouchPoint tracks a separate touch point, similar to how MouseArea tracks one mouse.
What will happen if TextInput or TextEdit doesn’t receive focus when a user attempts to enter text?Answer
Correct answer: Text input won’t work, since keyboard events are only processed by the element that has active focus. The user will have to first click on the element with the mouse to get focus.
Why is Repeater used in the multitouch example to create touch visualization?Answer
Correct answer: Repeater automatically creates visual elements (rectangles) for each TouchPoint from the array, eliminating the need to duplicate code for each touch and ensuring synchronization with modelData.
Practical Assignments
Easy Level
Interactive Business Card with Hover Effects
Create a rectangular business card containing your name and profession. On mouse cursor hover, the card should change background color, and on left-click — increase text font size. On right-click, the font size should decrease.
Hints: Use Rectangle with nested Text. In MouseArea set hoverEnabled: true to track hovering. Use the containsMouse property to change color. In the onPressed handler, check mouse.button and change font.pixelSize of text through parent or id.
Medium Level
Simple Calculator with Keyboard Input
Create a simple calculator with two TextInput fields for entering numbers and result display. The user should be able to switch between fields using the Tab key. Add handling of ‘+’, ‘-‘, ‘*’, ‘/’ keys to perform corresponding operations and display the result in a Text element. When Enter is pressed, the result should be copied to the first field.
Hints: Use two TextInput with configured KeyNavigation.tab. For handling arithmetic keys, use Keys.onPressed and check event.key (Qt.Key_Plus, etc.). To convert text to numbers, use parseFloat() or Number(). Validate input. Don’t forget to set focus: true for the first field.
Hard Level
Multitouch Drawing App with Action History
Create a drawing application supporting up to 5 simultaneous touches. Each touch should leave a trace as a colored line (different colors for different fingers). Implement a history of the last 10 touches displaying startX/startY coordinates, current x/y, and pressure. Add a canvas clear button with a custom clearRequested signal and the ability to undo the last action by pressing the ‘Z’ key.
Hints: Use MultiPointTouchArea with an array of TouchPoint. For drawing, use Canvas with the requestPaint() method. In onPressureChanged or onPositionChanged handlers, save coordinates in a JavaScript array. For history, create a ListModel with delegate elements. Create a custom button with signal clearRequested. For key handling, use Keys.onPressed with event.key == Qt.Key_Z check.
💬 Join the Discussion!
Figured out user input handling in QML? Have questions about choosing between signals and properties?
Share your experience implementing interactive elements, discuss the nuances of working with focus, or tell us about solving multitouch problems! Your experience can help other readers master these concepts faster.