Qt 6.x
The Qt SDK
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\section2 Property change signal handlers
58
59A signal is automatically emitted when the value of a QML property changes.
60This type of signal is a \e {property change signal} and signal handlers for
61these signals are written in the form \e on<Property>Changed, where
62\e <Property> is the name of the property, with the first letter capitalized.
63
64For example, the \l MouseArea type has a \l {MouseArea::pressed}{pressed} property.
65To receive a notification whenever this property changes, write a signal handler
66named \c onPressedChanged:
67
68\qml
69import QtQuick
70
71Rectangle {
72 id: rect
73 width: 100; height: 100
74
75 TapHandler {
76 onPressedChanged: console.log("taphandler pressed?", pressed)
77 }
78}
79\endqml
80
81Even though the \l TapHandler documentation does not document a signal handler
82named \c onPressedChanged, the signal is implicitly provided by the fact that
83the \c pressed property exists.
84
85\section2 Signal parameters
86
87Signals might have parameters. To access those, you should assign a function to the handler. Both
88arrow functions and anonymous functions work.
89
90For the following examples, consider a Status component with an errorOccurred signal (see
91\l{Adding signals to custom QML types} for more information about how signals can be added to
92QML components).
93
94\qml
95// Status.qml
96import QtQuick
97
98Item {
99 id: myitem
100 signal errorOccurred(message: string, line: int, column: int)
101}
102\endqml
103
104\qml
105Status {
106 onErrorOccurred: (mgs, line, col) => console.log(`${line}:${col}: ${msg}`)
107}
108\endqml
109
110\note The names of the formal parameters in the function do not have to match those in the
111signal.
112
113If you do not need to handle all parameters, it is possible to omit trailing ones:
114\qml
115Status {
116 onErrorOccurred: function (message) { console.log(message) }
117}
118\endqml
119
120It is not possible to leave out leading parameters you are interested in, however you can use some
121placeholder name to indicate to readers that they are not important:
122\qml
123Status {
124 onErrorOccurred: (_, _, col) => console.log(`Error happened at column ${col}`)
125}
126\endqml
127
128\note Instead of using a function, it is possible, but discouraged, to use a plain code block. In
129that case all signal parameters get injected into the scope of the block. However, this can make
130code difficult to read as it's unclear where the parameters come from, and results in slower
131lookups in the QML engine. Injecting parameters in this way is deprecated, and will cause runtime
132warnings if the parameter is actually used.
133
134\section2 Using the Connections type
135
136In some cases it may be desirable to access a signal outside of the object that
137emits it. For these purposes, the \c QtQuick module provides the \l Connections
138type for connecting to signals of arbitrary objects. A \l Connections object
139can receive any signal from its specified \l {Connections::target}{target}.
140
141For example, the \c onClicked handler in the earlier example could have been
142received by the root \l Rectangle instead, by placing the \c onClicked handler
143in a \l Connections object that has its \l {Connections::target}{target} set to
144the \c button:
145
146\qml
147import QtQuick
148import QtQuick.Controls
149
150Rectangle {
151 id: rect
152 width: 250; height: 250
153
154 Button {
155 id: button
156 anchors.bottom: parent.bottom
157 anchors.horizontalCenter: parent.horizontalCenter
158 text: "Change color!"
159 }
160
161 Connections {
162 target: button
163 function onClicked() {
164 rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
165 }
166 }
167}
168\endqml
169
170
171\section2 Attached signal handlers
172
173An \l {Attached Properties and Attached Signal Handlers}{attached signal handler}
174receives a signal from an \e {attaching type} rather than the object within which
175the handler is declared.
176
177For example, \l{Component::completed}{Component.onCompleted} is an attached
178signal handler. It is often used to execute some JavaScript code when its
179creation process is complete. Here is an example:
180
181\qml
182import QtQuick
183
184Rectangle {
185 width: 200; height: 200
186 color: Qt.rgba(Qt.random(), Qt.random(), Qt.random(), 1)
187
188 Component.onCompleted: {
189 console.log("The rectangle's color is", color)
190 }
191}
192\endqml
193
194The \c onCompleted handler is not responding to a \c completed signal from
195the \l Rectangle type. Instead, an object of the \c Component \e{attaching type}
196with a \c completed signal has automatically been \e attached to the \l Rectangle
197object by the QML engine. The engine emits this signal when the Rectangle object is
198created, thus triggering the \c Component.onCompleted signal handler.
199
200Attached signal handlers allow objects to be notified of particular signals that are
201significant to each individual object. If there was no \c Component.onCompleted
202attached signal handler, for example, an object could not receive this notification
203without registering for some special signal from some special object.
204The \e {attached signal handler} mechanism enables objects to receive particular
205signals without extra code.
206
207See \l {Attached properties and attached signal handlers} for more information on
208attached signal handlers.
209
210\section1 Adding signals to custom QML types
211
212Signals can be added to custom QML types through the \c signal keyword.
213
214The syntax for defining a new signal is:
215
216\tt{signal <name>[([<type> <parameter name>[, ...]])]}
217
218A signal is emitted by invoking the signal as a method.
219
220For example, the code below is defined in a file named \c SquareButton.qml. The
221root \l Rectangle object has an \c activated signal, which is emitted whenever the
222child \l TapHandler is \c tapped. In this particular example the activated signal
223is emitted with the x and y coordinates of the mouse click:
224
225\qml
226// SquareButton.qml
227import QtQuick
228
229Rectangle {
230 id: root
231
232 signal activated(real xPosition, real yPosition)
233 property point mouseXY
234 property int side: 100
235 width: side; height: side
236
237 TapHandler {
238 id: handler
239 onTapped: root.activated(root.mouseXY.x, root.mouseXY.y)
240 onPressedChanged: root.mouseXY = handler.point.position
241 }
242}
243\endqml
244
245Now any objects of the \c SquareButton can connect to the \c activated signal using an \c onActivated signal handler:
246
247\qml
248// myapplication.qml
249SquareButton {
250 onActivated: (xPosition, yPosition)=> console.log("Activated at " + xPosition + "," + yPosition)
251}
252\endqml
253
254See \l {Signal Attributes} for more details on writing signals for custom QML types.
255
256
257\target qml-connect-signals-to-method
258\section1 Connecting signals to methods and signals
259
260Signal objects have a \c connect() method to a connect a signal either to a
261method or another signal. When a signal is connected to a method, the method is
262automatically invoked whenever the signal is emitted. This mechanism enables a
263signal to be received by a method instead of a signal handler.
264
265Below, the \c messageReceived signal is connected to three methods using the \c connect() method:
266
267\qml
268import QtQuick
269
270Rectangle {
271 id: relay
272
273 signal messageReceived(string person, string notice)
274
275 Component.onCompleted: {
276 relay.messageReceived.connect(sendToPost)
277 relay.messageReceived.connect(sendToTelegraph)
278 relay.messageReceived.connect(sendToEmail)
279 relay.messageReceived("Tom", "Happy Birthday")
280 }
281
282 function sendToPost(person, notice) {
283 console.log("Sending to post: " + person + ", " + notice)
284 }
285 function sendToTelegraph(person, notice) {
286 console.log("Sending to telegraph: " + person + ", " + notice)
287 }
288 function sendToEmail(person, notice) {
289 console.log("Sending to email: " + person + ", " + notice)
290 }
291}
292\endqml
293
294In many cases it is sufficient to receive signals through signal handlers
295rather than using the connect() function. However, using the \c connect
296method allows a signal to be received by multiple methods as shown earlier,
297which would not be possible with signal handlers as they must be uniquely
298named. Also, the \c connect method is useful when connecting signals to
299\l {Dynamic QML Object Creation from JavaScript}{dynamically created objects}.
300
301There is a corresponding \c disconnect() method for removing connected signals:
302
303\qml
304Rectangle {
305 id: relay
306 //...
307
308 function removeTelegraphSignal() {
309 relay.messageReceived.disconnect(sendToTelegraph)
310 }
311}
312\endqml
313
314\section3 Signal to signal connect
315
316By connecting signals to other signals, the \c connect() method can form different
317signal chains.
318
319\qml
320import QtQuick
321
322Rectangle {
323 id: forwarder
324 width: 100; height: 100
325
326 signal send()
327 onSend: console.log("Send clicked")
328
329 TapHandler {
330 id: mousearea
331 anchors.fill: parent
332 onTapped: console.log("Mouse clicked")
333 }
334
335 Component.onCompleted: {
336 mousearea.tapped.connect(send)
337 }
338}
339\endqml
340
341
342Whenever the \l TapHandler's \c tapped signal is emitted, the \c send
343signal will automatically be emitted as well.
344
345\code
346output:
347 MouseArea clicked
348 Send clicked
349\endcode
350*/