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