Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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\section2 Using the Connections type
143
144In some cases it may be desirable to access a signal outside of the object that
145emits it. For these purposes, the \c QtQuick module provides the \l Connections
146type for connecting to signals of arbitrary objects. A \l Connections object
147can receive any signal from its specified \l {Connections::target}{target}.
148
149For example, the \c onClicked handler in the earlier example could have been
150received by the root \l Rectangle instead, by placing the \c onClicked handler
151in a \l Connections object that has its \l {Connections::target}{target} set to
152the \c button:
153
154\qml
155import QtQuick
156import QtQuick.Controls
157
158Rectangle {
159 id: rect
160 width: 250; height: 250
161
162 Button {
163 id: button
164 anchors.bottom: parent.bottom
165 anchors.horizontalCenter: parent.horizontalCenter
166 text: "Change color!"
167 }
168
169 Connections {
170 target: button
171 function onClicked() {
172 rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
173 }
174 }
175}
176\endqml
177
178
179\section2 Attached signal handlers
180
181An \l {Attached Properties and Attached Signal Handlers}{attached signal handler}
182receives a signal from an \e {attaching type} rather than the object within which
183the handler is declared.
184
185For example, \l{Component::completed}{Component.onCompleted} is an attached
186signal handler. It is often used to execute some JavaScript code when its
187creation process is complete. Here is an example:
188
189\qml
190import QtQuick
191
192Rectangle {
193 width: 200; height: 200
194 color: Qt.rgba(Qt.random(), Qt.random(), Qt.random(), 1)
195
196 Component.onCompleted: {
197 console.log("The rectangle's color is", color)
198 }
199}
200\endqml
201
202The \c onCompleted handler is not responding to a \c completed signal from
203the \l Rectangle type. Instead, an object of the \c Component \e{attaching type}
204with a \c completed signal has automatically been \e attached to the \l Rectangle
205object by the QML engine. The engine emits this signal when the Rectangle object is
206created, thus triggering the \c Component.onCompleted signal handler.
207
208Attached signal handlers allow objects to be notified of particular signals that are
209significant to each individual object. If there was no \c Component.onCompleted
210attached signal handler, for example, an object could not receive this notification
211without registering for some special signal from some special object.
212The \e {attached signal handler} mechanism enables objects to receive particular
213signals without extra code.
214
215See \l {Attached properties and attached signal handlers} for more information on
216attached signal handlers.
217
218\section1 Adding signals to custom QML types
219
220Signals can be added to custom QML types through the \c signal keyword.
221
222The syntax for defining a new signal is:
223
224\tt{signal <name>[([<type> <parameter name>[, ...]])]}
225
226A signal is emitted by invoking the signal as a method.
227
228For example, the code below is defined in a file named \c SquareButton.qml. The
229root \l Rectangle object has an \c activated signal, which is emitted whenever the
230child \l TapHandler is \c tapped. In this particular example the activated signal
231is emitted with the x and y coordinates of the mouse click:
232
233\qml
234// SquareButton.qml
235import QtQuick
236
237Rectangle {
238 id: root
239
240 signal activated(real xPosition, real yPosition)
241 property point mouseXY
242 property int side: 100
243 width: side; height: side
244
245 TapHandler {
246 id: handler
247 onTapped: root.activated(root.mouseXY.x, root.mouseXY.y)
248 onPressedChanged: root.mouseXY = handler.point.position
249 }
250}
251\endqml
252
253Now any objects of the \c SquareButton can connect to the \c activated signal using an \c onActivated signal handler:
254
255\qml
256// myapplication.qml
257SquareButton {
258 onActivated: (xPosition, yPosition) => console.log(`Activated at {xPosition}, ${yPosition}`)
259}
260\endqml
261
262See \l {Signal Attributes} for more details on writing signals for custom QML types.
263
264
265\target qml-connect-signals-to-method
266\section1 Connecting signals to methods and signals
267
268Signal objects have a \c connect() method to a connect a signal either to a
269method or another signal. When a signal is connected to a method, the method is
270automatically invoked whenever the signal is emitted. This mechanism enables a
271signal to be received by a method instead of a signal handler.
272
273Below, the \c messageReceived signal is connected to three methods using the \c connect() method:
274
275\qml
276import QtQuick
277
278Rectangle {
279 id: relay
280
281 signal messageReceived(string person, string notice)
282
283 Component.onCompleted: {
284 relay.messageReceived.connect(sendToPost)
285 relay.messageReceived.connect(sendToTelegraph)
286 relay.messageReceived.connect(sendToEmail)
287 relay.messageReceived("Tom", "Happy Birthday")
288 }
289
290 function sendToPost(person: string, notice: string) {
291 console.log(`Sending to post: ${person}, ${notice}`)
292 }
293 function sendToTelegraph(person: string, notice: string) {
294 console.log(`Sending to telegraph: ${person}, ${notice}`)
295 }
296 function sendToEmail(person: string, notice: string) {
297 console.log(`Sending to email: ${person}, ${notice}`)
298 }
299}
300\endqml
301
302In many cases it is sufficient to receive signals through signal handlers
303rather than using the connect() function. However, using the \c connect
304method allows a signal to be received by multiple methods as shown earlier,
305which would not be possible with signal handlers as they must be uniquely
306named. Also, the \c connect method is useful when connecting signals to
307\l {Dynamic QML Object Creation from JavaScript}{dynamically created objects}.
308
309There is a corresponding \c disconnect() method for removing connected signals:
310
311\qml
312Rectangle {
313 id: relay
314 //...
315
316 function removeTelegraphSignal() {
317 relay.messageReceived.disconnect(sendToTelegraph)
318 }
319}
320\endqml
321
322\section3 Signal to signal connect
323
324By connecting signals to other signals, the \c connect() method can form different
325signal chains.
326
327\qml
328import QtQuick
329
330Rectangle {
331 id: forwarder
332 width: 100; height: 100
333
334 signal send()
335 onSend: console.log("Send clicked")
336
337 TapHandler {
338 id: mousearea
339 anchors.fill: parent
340 onTapped: console.log("Mouse clicked")
341 }
342
343 Component.onCompleted: {
344 mousearea.tapped.connect(send)
345 }
346}
347\endqml
348
349
350Whenever the \l TapHandler's \c tapped signal is emitted, the \c send
351signal will automatically be emitted as well.
352
353\code
354output:
355 MouseArea clicked
356 Send clicked
357\endcode
358
359\note Connections to function objects will stay alive as long as the sender of the signal is alive.
360This behavior is analogous to the 3-argument version of QObject::connect() in C++.
361
362\qml
363Window {
364 visible: true
365 width: 400
366 height: 400
367
368 Item {
369 id: item
370 property color globalColor: "red"
371
372 Button {
373 text: "Change global color"
374 onPressed: {
375 item.globalColor = item.globalColor === Qt.color("red") ? "green" : "red"
376 }
377 }
378
379 Button {
380 x: 150
381 text: "Clear rectangles"
382 onPressed: repeater.model = 0
383 }
384
385 Repeater {
386 id: repeater
387 model: 5
388 Rectangle {
389 id: rect
390 color: "red"
391 width: 50
392 height: 50
393 x: (width + 2) * index + 2
394 y: 100
395 Component.onCompleted: {
396 if (index % 2 === 0) {
397 item.globalColorChanged.connect(() => {
398 color = item.globalColor
399 })
400 }
401 }
402 }
403 }
404 }
405}
406\endqml
407
408In the contrived example above, the goal is to flip the color of every even rectangle to follow
409some global color. To achieve this, for every even rectangle, a connection is made between the
410globalColorChanged signal and a function to set the rectangle's color. This works as expected while
411the rectangles are alive. However, once the clear button is pressed, the rectangles are gone but
412the function handling the signal is still called every time the signal is emitted. This can be
413seen by the error messages thrown by the function trying to run in the background when changing
414the global color.
415
416In the current setup, the connections would only be destroyed once the item holding
417globalColor is destroyed. To prevent the connections from lingering on, they can be explicitly
418disconnected when the rectangles are being destroyed.
419 */