On this page

C

Signal and handler event system

Application and user interface components need to communicate with each other. For example, a button needs to know when the user clicks on it. The button may change colors to indicate its state or perform some logic. In addition, the application needs to know whether the user clicks the button. The application may need to relay this click event to other applications.

QML has a signal and handler mechanism, where the signal is the event and the signal gets responses through a signal handler. When a signal is emitted, the corresponding signal handler is invoked. Placing logic such as a script or other operations in the handler allows the component to respond to the event.

Receiving signals with signal handlers

To receive notification about a particular signal for an object, the object definition should declare a signal handler named on<Signal>, where <Signal> is the name of the signal, with the first letter capitalized. The signal handler should use JavaScript code, which is run every time the signal handler is invoked.

For example, the Button type from the Qt Quick Ultralite Controls module emits the clicked signal every time the button is clicked. The corresponding signal handler for receiving this signal should be onClicked. The following example invokes the onClicked handler for every button click, applying a random color to the parent Rectangle:

import QtQuick
import QtQuick.Controls

Rectangle {
    id: rect
    width: 250; height: 250

    Button {
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        text: "Change color!"
        onClicked: {
            rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
        }
    }
}

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. Another alternative is to always emit the signal to invoke the signal handler. You can define many handlers, in different scopes, for the same signal.

Property change signal handlers

A property change signal is emitted when the value of a QML property changes. The signal handlers for such signals are written in the form on<Property>Changed, where <Property> is the name of the property, with the first letter capitalized.

For example, the MouseArea type has a pressed property. To receive a notification whenever this property changes, write a signal handler named onPressedChanged:

import QtQuick

Rectangle {
    id: rect
    width: 100; height: 100

    MouseArea {
        onPressedChanged: console.log("MouseArea pressed?", pressed)
    }
}

Even though the MouseArea documentation does not document a signal handler named onPressedChanged, the signal is implicitly provided by the fact that the pressed property exists.

Signal parameters

Signals can have parameters. To access those, you need to assign a function to the handler.

For the following examples, consider a Status component with an errorOccurred signal.

// Status.qml
import QtQuick

Item {
    id: myitem

    signal errorOccurred(message: string, line: int, column: int)
}
Status {
    onErrorOccurred: console.log(`${line}:${column}: ${message}`)
}

Note: All signal parameters get injected into the scope of the block.

Using the Connections type

In some cases, you may want to access a signal outside of the object that emits it. The QtQuick module provides the Connections QML type for connecting to signals of arbitrary objects. A Connections object can receive any signal from its target.

In the earlier example, the root Rectangle in the onClicked handler could also receive a signal. This is possible by placing the onClicked handler in a Connections object that has its target set to the button:

import QtQuick
import QtQuick.Controls

Rectangle {
    id: rect
    width: 250; height: 250

    Button {
        id: button
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        text: "Change color!"
    }

    Connections {
        target: button
        function onClicked(event: MouseEvent) {
            rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
        }
    }
}

Attached signal handlers

An attached signal handler receives a signal from an attaching type rather than the object within which the handler is declared.

For example, Component.onCompleted is an attached signal handler. It is often used to execute some JavaScript code when its creation process is complete. Here is an example:

import QtQuick

Rectangle {
    width: 200; height: 200
    color: Qt.rgba(Qt.random(), Qt.random(), Qt.random(), 1)

    Component.onCompleted: {
        console.log("The rectangle's color is", color)
    }
}

The onCompleted handler is not responding to a completed signal from the Rectangle type. Instead, an object of the Component attaching type with a completed signal has automatically been attached to the Rectangle object by the QML engine. The engine emits this signal when the Rectangle object is created, thus triggering the Component.onCompleted signal handler.

Attached signal handlers allow objects to be notified of particular signals that are significant to each individual object. If there was no Component.onCompleted attached signal handler, for example, an object could not receive this notification without registering for some special signal from some special object. The attached signal handler mechanism enables objects to receive particular signals without extra code.

See attached properties and attached signal handlers for more information on attached signal handlers.

Adding signals to custom QML types

Signals can be added to custom QML types through the signal keyword.

The syntax for defining a new signal is:

signal <name>[([<type> <parameter name>[, ...]])]

A signal is emitted by invoking the signal as a method.

For example, the code below is defined in a file named SquareButton.qml. The root Rectangle object has an activated signal, which is emitted whenever the child MouseArea is tapped. In this particular example the activated signal is emitted with the x and y coordinates of the mouse click:

// SquareButton.qml
import QtQuick

Rectangle {
    id: root

    signal activated(real xPosition, real yPosition)
    property point mouseXY
    property int side: 100
    width: side; height: side

    MouseArea {
        id: handler
        onPressed: {
            rect.mouseXY = Qt.point(mouseX, mouseY)
            rect.activated(rect.mouseXY.x, rect.mouseXY.y)
        }
    }
}

Now any objects of the SquareButton can connect to the activated signal using an onActivated signal handler:

// myapplication.qml
SquareButton {
    onActivated: console.log(`Activated at {xPosition}, ${yPosition}`)
}

See signal attributes for more details on writing signals for custom QML types.

Available under certain Qt licenses.
Find out more.