Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
signals.qdoc
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4/*!
5\page qtqml-syntax-signals.html
6\meta {keywords} {qmltopic}
7
8\title Signal and Handler Event System
9\brief the event system in QML
10
11Application and user interface components need to communicate with each other. For
12example, a button needs to know that the user has clicked on it.
13The button may change colors to indicate its state or perform some logic. As
14well, application needs to know whether the user is clicking the button. The
15application may need to relay this clicking event to other applications.
16
17QML has a signal and handler mechanism, where the \e signal is the event
18and the signal is responded to through a \e {signal handler}. When a signal
19is emitted, the corresponding signal handler is invoked. Placing logic such as
20a script or other operations in the handler allows the component to respond to
21the event.
22
23\target qml-signals-and-handlers
24\section1 Receiving signals with signal handlers
25
26To receive a notification when a particular signal is emitted for a particular
27object, the object definition should declare a signal handler named
28\e on<Signal>, where \e <Signal> is the name of the signal, with the first
29letter capitalized. The signal handler should contain the JavaScript code to be
30executed when the signal handler is invoked.
31
32For example, the \l [QtQuickControls]{Button} type from the
33\l{Qt Quick Controls} module has a \c clicked signal, which
34is emitted whenever the button is clicked. In this case, the signal handler for
35receiving this signal should be \c onClicked. In the example below, whenever
36the button is clicked, the \c onClicked handler is invoked, applying a random
37color to the parent \l Rectangle:
38
39\qml
40import QtQuick
41import QtQuick.Controls
42
43Rectangle {
44 id: rect
45 width: 250; height: 250
46
47 Button {
48 anchors.bottom: parent.bottom
49 anchors.horizontalCenter: parent.horizontalCenter
50 text: "Change color!"
51 onClicked: {
52 rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
53 }
54 }
55}
56\endqml
57
58\note Even though signal handlers look a bit like JavaScript functions, you
59 should not call them directly. If you need to share code between signal
60 handlers and other functionality, refactor it into a separate function.
61 Otherwise always emit the signal if you want the signal handler to be
62 called. There can be multiple handlers, in different scopes, for the
63 same signal.
64
65\section2 Property change signal handlers
66
67A signal is automatically emitted when the value of a QML property changes.
68This type of signal is a \e {property change signal} and signal handlers for
69these signals are written in the form \e on<Property>Changed, where
70\e <Property> is the name of the property, with the first letter capitalized.
71
72For example, the \l MouseArea type has a \l {MouseArea::pressed}{pressed} property.
73To receive a notification whenever this property changes, write a signal handler
74named \c onPressedChanged:
75
76\qml
77import QtQuick
78
79Rectangle {
80 id: rect
81 width: 100; height: 100
82
83 TapHandler {
84 onPressedChanged: console.log("taphandler pressed?", pressed)
85 }
86}
87\endqml
88
89Even though the \l TapHandler documentation does not document a signal handler
90named \c onPressedChanged, the signal is implicitly provided by the fact that
91the \c pressed property exists.
92
93\section2 Signal parameters
94
95Signals might have parameters. To access those, you should assign a function to the handler. Both
96arrow functions and anonymous functions work.
97
98For the following examples, consider a Status component with an errorOccurred signal (see
99\l{Adding signals to custom QML types} for more information about how signals can be added to
100QML components).
101
102\qml
103// Status.qml
104import QtQuick
105
106Item {
107 id: myitem
108
109 signal errorOccurred(message: string, line: int, column: int)
110}
111\endqml
112
113\qml
114Status {
115 onErrorOccurred: (mgs, line, col) => console.log(`${line}:${col}: ${msg}`)
116}
117\endqml
118
119\note The names of the formal parameters in the function do not have to match those in the
120signal.
121
122If you do not need to handle all parameters, it is possible to omit trailing ones:
123\qml
124Status {
125 onErrorOccurred: message => console.log(message)
126}
127\endqml
128
129It is not possible to leave out leading parameters you are interested in, however you can use some
130placeholder name to indicate to readers that they are not important:
131\qml
132Status {
133 onErrorOccurred: (_, _, col) => console.log(`Error happened at column ${col}`)
134}
135\endqml
136
137\note Instead of using a function, it is possible, but discouraged, to use a plain code block. In
138that case all signal parameters get injected into the scope of the block. However, this can make
139code difficult to read as it's unclear where the parameters come from, and results in slower
140lookups in the QML engine. Injecting parameters in this way is deprecated, and will cause runtime
141warnings if the parameter is actually used.
142
143\section3 Using the arguments special object
144
145In JavaScript you can refer to the \c arguments special
146object, which, when available, allows to access the values of the
147arguments passed to a non-arrow function as an array-like object.
148
149It is usually available in the body of a function or code block that
150is assigned to a signal handler.
151
152When a code block or an anonymous function is assigned to the signal
153handler, the special \c arguments object will provide the arguments
154that were passed over by the signal.
155
156For example, both of the following will print \c{[object Arguments] world undefined}:
157
158\qml
159import QtQml
160
161QtObject {
162 id: root
163
164 signal hello(message: string)
165
166 onHello: { console.log(arguments, arguments[0], arguments[1]) }
167
168 Component.onCompleted: root.hello("world")
169}
170\endqml
171
172\qml
173import QtQml
174
175QtObject {
176 id: root
177
178 signal hello(message: string)
179
180 onHello: function () { console.log(arguments, arguments[0], arguments[1]) }
181
182 Component.onCompleted: root.hello("world")
183}
184\endqml
185
186The behavior will differ when an arrow function is assigned to the signal handler.
187Then, it will still be possible to access the \c arguments
188special object, but it will be an empty array-like object.
189
190For example, the following will print \c{[object Arguments] undefined undefined}:
191
192\qml
193import QtQml
194
195QtObject {
196 id: root
197
198 signal hello(message: string)
199
200 onHello: () => { console.log(arguments, arguments[0], arguments[1]) }
201
202 Component.onCompleted: root.hello("world")
203}
204\endqml
205
206The difference in behavior is due to the way the \c{arguments} special
207object interacts with arrow functions but is consistent with the general
208behavior for bindings.
209
210By specification, an arrow function does not carry its own
211\c arguments special object.
212As an arrow function still borrows from its enclosing context, it can
213borrow the \c arguments special object if one is available.
214
215A binding provides its own scope on evaluation.
216In particular, the retrieval of the underlying arrow function is
217performed in the scope provided by the evaluation of the binding.
218
219In the scope of the binding no argument is provided, such that an
220empty \c arguments special object will be available and borrowed by
221the arrow function on retrieval.
222
223As a non-arrow function does provide the \c arguments special object
224in its own scope it can refer to the arguments that were provided to
225the underlying function itself, which are the forwarded arguments
226provided by the signal.
227
228Usage of the \c arguments special object should generally be avoided
229in favor of the usage of named parameters, which are more explicit and
230work consistently independently of the usage of an arrow or a non-arrow
231function.
232
233\section2 Using the Connections type
234
235In some cases it may be desirable to access a signal outside of the object that
236emits it. For these purposes, the \c QtQuick module provides the \l Connections
237type for connecting to signals of arbitrary objects. A \l Connections object
238can receive any signal from its specified \l {Connections::target}{target}.
239
240For example, the \c onClicked handler in the earlier example could have been
241received by the root \l Rectangle instead, by placing the \c onClicked handler
242in a \l Connections object that has its \l {Connections::target}{target} set to
243the \c button:
244
245\qml
246import QtQuick
247import QtQuick.Controls
248
249Rectangle {
250 id: rect
251 width: 250; height: 250
252
253 Button {
254 id: button
255 anchors.bottom: parent.bottom
256 anchors.horizontalCenter: parent.horizontalCenter
257 text: "Change color!"
258 }
259
260 Connections {
261 target: button
262 function onClicked() {
263 rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
264 }
265 }
266}
267\endqml
268
269
270\section2 Attached signal handlers
271
272An \l {Attached Properties and Attached Signal Handlers}{attached signal handler}
273receives a signal from an \e {attaching type} rather than the object within which
274the handler is declared.
275
276For example, \l{Component::completed}{Component.onCompleted} is an attached
277signal handler. It is often used to execute some JavaScript code when its
278creation process is complete. Here is an example:
279
280\qml
281import QtQuick
282
283Rectangle {
284 width: 200; height: 200
285 color: Qt.rgba(Qt.random(), Qt.random(), Qt.random(), 1)
286
287 Component.onCompleted: {
288 console.log("The rectangle's color is", color)
289 }
290}
291\endqml
292
293The \c onCompleted handler is not responding to a \c completed signal from
294the \l Rectangle type. Instead, an object of the \c Component \e{attaching type}
295with a \c completed signal has automatically been \e attached to the \l Rectangle
296object by the QML engine. The engine emits this signal when the Rectangle object is
297created, thus triggering the \c Component.onCompleted signal handler.
298
299Attached signal handlers allow objects to be notified of particular signals that are
300significant to each individual object. If there was no \c Component.onCompleted
301attached signal handler, for example, an object could not receive this notification
302without registering for some special signal from some special object.
303The \e {attached signal handler} mechanism enables objects to receive particular
304signals without extra code.
305
306See \l {Attached properties and attached signal handlers} for more information on
307attached signal handlers.
308
309\section1 Adding signals to custom QML types
310
311Signals can be added to custom QML types through the \c signal keyword.
312
313The preferred syntax for defining a new signal is:
314
315\tt{signal <name>[([<parameter name> : <type>[, ...]])]}
316
317There is also an old syntax with the type before the name:
318
319\tt{signal <name>[([<type> <parameter name>[, ...]])]}
320
321You should use the new syntax.
322
323A signal is emitted by invoking the signal as a method.
324
325For example, the code below is defined in a file named \c SquareButton.qml. The
326root \l Rectangle object has an \c activated signal, which is emitted whenever the
327child \l TapHandler is \c tapped. In this particular example the activated signal
328is emitted with the x and y coordinates of the mouse click:
329
330\qml
331// SquareButton.qml
332import QtQuick
333
334Rectangle {
335 id: root
336
337 signal activated(xPosition: real, yPosition: real)
338 property point mouseXY
339 property int side: 100
340 width: side; height: side
341
342 TapHandler {
343 id: handler
344 onTapped: root.activated(root.mouseXY.x, root.mouseXY.y)
345 onPressedChanged: root.mouseXY = handler.point.position
346 }
347}
348\endqml
349
350Now any objects of the \c SquareButton can connect to the \c activated signal using an \c onActivated signal handler:
351
352\qml
353// myapplication.qml
354SquareButton {
355 onActivated: (xPosition, yPosition) => console.log(`Activated at {xPosition}, ${yPosition}`)
356}
357\endqml
358
359See \l {Signal Attributes} for more details on writing signals for custom QML types.
360
361
362\target qml-connect-signals-to-method
363\section1 Connecting signals to methods and signals
364
365Signal objects have a \c connect() method to a connect a signal either to a
366method or another signal. When a signal is connected to a method, the method is
367automatically invoked whenever the signal is emitted. This mechanism enables a
368signal to be received by a method instead of a signal handler.
369
370Below, the \c messageReceived signal is connected to three methods using the \c connect() method:
371
372\qml
373import QtQuick
374
375Rectangle {
376 id: relay
377
378 signal messageReceived(person: string, notice: string)
379
380 Component.onCompleted: {
381 relay.messageReceived.connect(sendToPost)
382 relay.messageReceived.connect(sendToTelegraph)
383 relay.messageReceived.connect(sendToEmail)
384 relay.messageReceived("Tom", "Happy Birthday")
385 }
386
387 function sendToPost(person: string, notice: string) {
388 console.log(`Sending to post: ${person}, ${notice}`)
389 }
390 function sendToTelegraph(person: string, notice: string) {
391 console.log(`Sending to telegraph: ${person}, ${notice}`)
392 }
393 function sendToEmail(person: string, notice: string) {
394 console.log(`Sending to email: ${person}, ${notice}`)
395 }
396}
397\endqml
398
399In many cases it is sufficient to receive signals through signal handlers
400rather than using the connect() function. However, using the \c connect
401method allows a signal to be received by multiple methods as shown earlier,
402which would not be possible with signal handlers as they must be uniquely
403named. Also, the \c connect method is useful when connecting signals to
404\l {Dynamic QML Object Creation from JavaScript}{dynamically created objects}.
405
406There is a corresponding \c disconnect() method for removing connected signals:
407
408\qml
409Rectangle {
410 id: relay
411 //...
412
413 function removeTelegraphSignal() {
414 relay.messageReceived.disconnect(sendToTelegraph)
415 }
416}
417\endqml
418
419\section3 Signal to signal connect
420
421By connecting signals to other signals, the \c connect() method can form different
422signal chains.
423
424\qml
425import QtQuick
426
427Rectangle {
428 id: forwarder
429 width: 100; height: 100
430
431 signal send()
432 onSend: console.log("Send clicked")
433
434 TapHandler {
435 id: mousearea
436 anchors.fill: parent
437 onTapped: console.log("Mouse clicked")
438 }
439
440 Component.onCompleted: {
441 mousearea.tapped.connect(send)
442 }
443}
444\endqml
445
446
447Whenever the \l TapHandler's \c tapped signal is emitted, the \c send
448signal will automatically be emitted as well.
449
450\code
451output:
452 MouseArea clicked
453 Send clicked
454\endcode
455
456\note Connections to function objects will stay alive as long as the sender of the signal is alive.
457This behavior is analogous to the 3-argument version of QObject::connect() in C++.
458
459\qml
460Window {
461 visible: true
462 width: 400
463 height: 400
464
465 Item {
466 id: item
467 property color globalColor: "red"
468
469 Button {
470 text: "Change global color"
471 onPressed: {
472 item.globalColor = item.globalColor === Qt.color("red") ? "green" : "red"
473 }
474 }
475
476 Button {
477 x: 150
478 text: "Clear rectangles"
479 onPressed: repeater.model = 0
480 }
481
482 Repeater {
483 id: repeater
484 model: 5
485 Rectangle {
486 id: rect
487 color: "red"
488 width: 50
489 height: 50
490 x: (width + 2) * index + 2
491 y: 100
492 Component.onCompleted: {
493 if (index % 2 === 0) {
494 item.globalColorChanged.connect(() => {
495 color = item.globalColor
496 })
497 }
498 }
499 }
500 }
501 }
502}
503\endqml
504
505In the contrived example above, the goal is to flip the color of every even rectangle to follow
506some global color. To achieve this, for every even rectangle, a connection is made between the
507globalColorChanged signal and a function to set the rectangle's color. This works as expected while
508the rectangles are alive. However, once the clear button is pressed, the rectangles are gone but
509the function handling the signal is still called every time the signal is emitted. This can be
510seen by the error messages thrown by the function trying to run in the background when changing
511the global color.
512
513In the current setup, the connections would only be destroyed once the item holding
514globalColor is destroyed. To prevent the connections from lingering on, they can be explicitly
515disconnected when the rectangles are being destroyed.
516 */