diff options
Diffstat (limited to 'src/qml/doc/src/qmllanguageref/syntax/signals.qdoc')
-rw-r--r-- | src/qml/doc/src/qmllanguageref/syntax/signals.qdoc | 168 |
1 files changed, 132 insertions, 36 deletions
diff --git a/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc b/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc index 1c13636689..b40181b49c 100644 --- a/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc +++ b/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc @@ -1,29 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! \page qtqml-syntax-signals.html @@ -78,6 +54,13 @@ Rectangle { } \endqml +\note Even though signal handlers look a bit like JavaScript functions, you + should not call them directly. If you need to share code between signal + handlers and other functionality, refactor it into a separate function. + Otherwise always emit the signal if you want the signal handler to be + called. There can be multiple handlers, in different scopes, for the + same signal. + \section2 Property change signal handlers A signal is automatically emitted when the value of a QML property changes. @@ -85,7 +68,9 @@ This type of signal is a \e {property change signal} and signal handlers for these signals are written in the form \e on<Property>Changed, where \e <Property> is the name of the property, with the first letter capitalized. -For example, the \l MouseArea type has a \l {MouseArea::pressed}{pressed} property. To receive a notification whenever this property changes, write a signal handler named \c onPressedChanged: +For example, the \l MouseArea type has a \l {MouseArea::pressed}{pressed} property. +To receive a notification whenever this property changes, write a signal handler +named \c onPressedChanged: \qml import QtQuick @@ -104,6 +89,56 @@ Even though the \l TapHandler documentation does not document a signal handler named \c onPressedChanged, the signal is implicitly provided by the fact that the \c pressed property exists. +\section2 Signal parameters + +Signals might have parameters. To access those, you should assign a function to the handler. Both +arrow functions and anonymous functions work. + +For the following examples, consider a Status component with an errorOccurred signal (see +\l{Adding signals to custom QML types} for more information about how signals can be added to +QML components). + +\qml +// Status.qml +import QtQuick + +Item { + id: myitem + + signal errorOccurred(message: string, line: int, column: int) +} +\endqml + +\qml +Status { + onErrorOccurred: (mgs, line, col) => console.log(`${line}:${col}: ${msg}`) +} +\endqml + +\note The names of the formal parameters in the function do not have to match those in the +signal. + +If you do not need to handle all parameters, it is possible to omit trailing ones: +\qml +Status { + onErrorOccurred: message => console.log(message) +} +\endqml + +It is not possible to leave out leading parameters you are interested in, however you can use some +placeholder name to indicate to readers that they are not important: +\qml +Status { + onErrorOccurred: (_, _, col) => console.log(`Error happened at column ${col}`) +} +\endqml + +\note Instead of using a function, it is possible, but discouraged, to use a plain code block. In +that case all signal parameters get injected into the scope of the block. However, this can make +code difficult to read as it's unclear where the parameters come from, and results in slower +lookups in the QML engine. Injecting parameters in this way is deprecated, and will cause runtime +warnings if the parameter is actually used. + \section2 Using the Connections type In some cases it may be desirable to access a signal outside of the object that @@ -133,7 +168,7 @@ Rectangle { Connections { target: button - function onClicked(): { + function onClicked() { rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1); } } @@ -220,7 +255,7 @@ Now any objects of the \c SquareButton can connect to the \c activated signal us \qml // myapplication.qml SquareButton { - onActivated: (xPosition, yPosition)=> console.log("Activated at " + xPosition + "," + yPosition) + onActivated: (xPosition, yPosition) => console.log(`Activated at {xPosition}, ${yPosition}`) } \endqml @@ -252,14 +287,14 @@ Rectangle { relay.messageReceived("Tom", "Happy Birthday") } - function sendToPost(person, notice) { - console.log("Sending to post: " + person + ", " + notice) + function sendToPost(person: string, notice: string) { + console.log(`Sending to post: ${person}, ${notice}`) } - function sendToTelegraph(person, notice) { - console.log("Sending to telegraph: " + person + ", " + notice) + function sendToTelegraph(person: string, notice: string) { + console.log(`Sending to telegraph: ${person}, ${notice}`) } - function sendToEmail(person, notice) { - console.log("Sending to email: " + person + ", " + notice) + function sendToEmail(person: string, notice: string) { + console.log(`Sending to email: ${person}, ${notice}`) } } \endqml @@ -320,4 +355,65 @@ output: MouseArea clicked Send clicked \endcode -*/ + +\note Connections to function objects will stay alive as long as the sender of the signal is alive. +This behavior is analogous to the 3-argument version of QObject::connect() in C++. + +\qml +Window { + visible: true + width: 400 + height: 400 + + Item { + id: item + property color globalColor: "red" + + Button { + text: "Change global color" + onPressed: { + item.globalColor = item.globalColor === Qt.color("red") ? "green" : "red" + } + } + + Button { + x: 150 + text: "Clear rectangles" + onPressed: repeater.model = 0 + } + + Repeater { + id: repeater + model: 5 + Rectangle { + id: rect + color: "red" + width: 50 + height: 50 + x: (width + 2) * index + 2 + y: 100 + Component.onCompleted: { + if (index % 2 === 0) { + item.globalColorChanged.connect(() => { + color = item.globalColor + }) + } + } + } + } + } +} +\endqml + +In the contrived example above, the goal is to flip the color of every even rectangle to follow +some global color. To achieve this, for every even rectangle, a connection is made between the +globalColorChanged signal and a function to set the rectangle's color. This works as expected while +the rectangles are alive. However, once the clear button is pressed, the rectangles are gone but +the function handling the signal is still called every time the signal is emitted. This can be +seen by the error messages thrown by the function trying to run in the background when changing +the global color. + +In the current setup, the connections would only be destroyed once the item holding +globalColor is destroyed. To prevent the connections from lingering on, they can be explicitly +disconnected when the rectangles are being destroyed. + */ |