Auf dieser Seite

Signal- und Handler-Ereignissystem

Anwendungs- und Benutzeroberflächenkomponenten müssen miteinander kommunizieren. Beispielsweise muss eine Schaltfläche wissen, dass der Benutzer darauf geklickt hat. Die Schaltfläche kann ihre Farbe ändern, um ihren Zustand anzuzeigen, oder eine bestimmte Logik ausführen. Ebenso muss die Anwendung wissen, ob der Benutzer auf die Schaltfläche klickt. Die Anwendung muss dieses Klickereignis möglicherweise an andere Anwendungen weiterleiten.

QML verfügt über einen Signal- und Handler-Mechanismus, bei dem das Signal das Ereignis darstellt und über einen Signal-Handler darauf reagiert wird. Wenn ein Signal ausgesendet wird, wird der entsprechende Signal-Handler aufgerufen. Durch das Einfügen von Logik wie einem Skript oder anderen Operationen in den Handler kann die Komponente auf das Ereignis reagieren.

Empfangen von Signalen mit Signal-Handlern

Um eine Benachrichtigung zu erhalten, wenn ein bestimmtes Signal für ein bestimmtes Objekt ausgesendet wird, sollte die Objektdefinition einen Signal-Handler mit dem Namen „on<Signal>“ deklarieren, wobei <Signal> der Name des Signals ist und der erste Buchstabe großgeschrieben wird. Der Signal-Handler sollte den JavaScript-Code enthalten, der ausgeführt werden soll, wenn der Signal-Handler aufgerufen wird.

Beispielsweise verfügt der Typ „ Button “ aus dem Qt Quick Controls Moduls verfügt über ein Signal „ clicked “, das immer dann ausgesendet wird, wenn auf die Schaltfläche geklickt wird. In diesem Fall sollte der Signal-Handler zum Empfangen dieses Signals „ onClicked “ lauten. Im folgenden Beispiel wird bei jedem Klick auf die Schaltfläche der Handler „ onClicked “ aufgerufen, wodurch dem übergeordneten Element „ Rectangle “ eine zufällige Farbe zugewiesen wird:

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);
        }
    }
}

Hinweis: Auch wenn Signal-Handler ein wenig wie JavaScript-Funktionen aussehen, sollten Sie sie nicht direkt aufrufen. Wenn Sie Code zwischen Signal-Handlern und anderen Funktionen gemeinsam nutzen müssen, refaktorisieren Sie ihn in eine separate Funktion. Andernfalls senden Sie immer das Signal aus, wenn Sie möchten, dass der Signal-Handler aufgerufen wird. Es kann mehrere Handler in unterschiedlichen Gültigkeitsbereichen für dasselbe Signal geben.

Signal-Handler für Eigenschaftsänderungen

Ein Signal wird automatisch ausgesendet, wenn sich der Wert einer QML-Eigenschaft ändert. Diese Art von Signal wird als Signal bei Eigenschaftsänderung bezeichnet, und Signalhandler für diese Signale werden in der Form on<Property>Changed geschrieben, wobei <Property> der Name der Eigenschaft ist und der erste Buchstabe großgeschrieben wird.

Beispielsweise verfügt der Typ „ MouseArea “ über die Eigenschaft „ pressed “. Um eine Benachrichtigung zu erhalten, sobald sich diese Eigenschaft ändert, schreiben Sie einen Signalhandler mit dem Namen „ onPressedChanged “:

import QtQuick

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

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

Auch wenn in der Dokumentation zu „ TapHandler “ kein Signal-Handler namens „ onPressedChanged “ dokumentiert ist, wird das Signal implizit durch die Existenz der Eigenschaft „ pressed “ bereitgestellt.

Signalparameter

Signale können Parameter haben. Um auf diese zuzugreifen, sollten Sie dem Handler eine Funktion zuweisen. Sowohl Pfeilfunktionen als auch anonyme Funktionen funktionieren.

Betrachten Sie für die folgenden Beispiele eine Status-Komponente mit einem „errorOccurred“-Signal (weitere Informationen darüber, wie Signale zu QML-Komponenten hinzugefügt werden können, finden Sie unter „Signale zu benutzerdefinierten QML-Typen hinzufügen“ ).

// Status.qml
import QtQuick

Item {
    id: myitem

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

Hinweis: Die Namen der formalen Parameter in der Funktion müssen nicht mit denen im Signal übereinstimmen.

Wenn Sie nicht alle Parameter verarbeiten müssen, können Sie die nachfolgenden weglassen:

Status {
    onErrorOccurred: message => console.log(message)
}

Es ist nicht möglich, führende Parameter, die für Sie von Interesse sind, wegzulassen; Sie können jedoch einen Platzhalternamen verwenden, um den Lesern zu signalisieren, dass diese nicht wichtig sind:

Status {
    onErrorOccurred: (_, _, col) => console.log(`Error happened at column ${col}`)
}

Hinweis: Anstelle einer Funktion ist es zwar möglich, aber nicht empfohlen, einen einfachen Codeblock zu verwenden. In diesem Fall werden alle Signalparameter in den Geltungsbereich des Blocks eingefügt. Dies kann jedoch die Lesbarkeit des Codes beeinträchtigen, da unklar ist, woher die Parameter stammen, und führt zu langsameren Abfragen in der QML-Engine. Das Einfügen von Parametern auf diese Weise ist veraltet und führt zu Laufzeitwarnungen, wenn der Parameter tatsächlich verwendet wird.

Verwendung des speziellen Objekts „arguments“

In JavaScript können Sie auf das Spezialobjekt „ arguments “ verweisen, das – sofern verfügbar – den Zugriff auf die Werte der an eine Nicht-Pfeilfunktion übergebenen Argumente als arrayähnliches Objekt ermöglicht.

Es steht in der Regel im Körper einer Funktion oder eines Codeblocks zur Verfügung, der einem Signal-Handler zugewiesen ist.

Wird dem Signal-Handler ein Codeblock oder eine anonyme Funktion zugewiesen, stellt das spezielle Objekt ` arguments ` die Argumente bereit, die vom Signal übergeben wurden.

Beispielsweise geben beide der folgenden Anweisungen „ [object Arguments] world undefined “ aus:

import QtQml

QtObject {
    id: root

    signal hello(message: string)

    onHello: { console.log(arguments, arguments[0], arguments[1]) }

    Component.onCompleted: root.hello("world")
}
import QtQml

QtObject {
    id: root

    signal hello(message: string)

    onHello: function () { console.log(arguments, arguments[0], arguments[1]) }

    Component.onCompleted: root.hello("world")
}

Das Verhalten unterscheidet sich, wenn dem Signal-Handler eine Pfeilfunktion zugewiesen wird. In diesem Fall ist der Zugriff auf das Spezialobjekt „ arguments “ zwar weiterhin möglich, es handelt sich dabei jedoch um ein leeres, arrayähnliches Objekt.

Beispielsweise gibt der folgende Code „ [object Arguments] undefined undefined “ aus:

import QtQml

QtObject {
    id: root

    signal hello(message: string)

    onHello: () => { console.log(arguments, arguments[0], arguments[1]) }

    Component.onCompleted: root.hello("world")
}

Der Unterschied im Verhalten ist auf die Art und Weise zurückzuführen, wie das Spezialobjekt ` arguments ` mit Pfeilfunktionen interagiert, steht jedoch im Einklang mit dem allgemeinen Verhalten bei Bindungen.

Gemäß der Spezifikation verfügt eine Pfeilfunktion nicht über ein eigenes „ arguments “-Spezialobjekt. Da eine Pfeilfunktion weiterhin aus ihrem umgebenden Kontext entlehnt, kann sie das „ arguments “-Spezialobjekt entlehnen, sofern eines verfügbar ist.

Eine Bindung stellt bei der Auswertung einen eigenen Gültigkeitsbereich bereit. Insbesondere erfolgt das Abrufen der zugrunde liegenden Pfeilfunktion in dem Gültigkeitsbereich, der durch die Auswertung der Bindung bereitgestellt wird.

Im Geltungsbereich der Bindung wird kein Argument bereitgestellt, sodass ein leeres Spezialobjekt „ arguments “ verfügbar ist und bei der Abfrage von der Pfeilfunktion übernommen wird.

Da eine Nicht-Pfeilfunktion das Spezialobjekt ` arguments ` in ihrem eigenen Geltungsbereich bereitstellt, kann sie auf die Argumente verweisen, die der zugrunde liegenden Funktion selbst übergeben wurden – also auf die vom Signal weitergeleiteten Argumente.

Die Verwendung des Spezialobjekts ` arguments ` sollte generell vermieden werden; stattdessen sollten benannte Parameter verwendet werden, die expliziter sind und unabhängig davon, ob eine Pfeilfunktion oder eine Nicht-Pfeilfunktion verwendet wird, konsistent funktionieren.

Verwendung des Typs „Connections“

In manchen Fällen kann es wünschenswert sein, auf ein Signal außerhalb des Objekts zuzugreifen, das es aussendet. Zu diesem Zweck stellt das Modul „ QtQuick “ den Typ „ Connections “ zur Verfügung, um eine Verbindung zu Signalen beliebiger Objekte herzustellen. Ein „ Connections “-Objekt kann jedes beliebige Signal von seinem angegebenen „ target “ empfangen.

Beispielsweise hätte der ` onClicked `-Handler aus dem vorherigen Beispiel stattdessen vom Stamm-` Rectangle ` empfangen werden können, indem man den ` onClicked `-Handler in ein ` Connections `-Objekt einfügt, dessen ` target ` auf den ` button` gesetzt ist:

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() {
            rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
        }
    }
}

Angehängte Signal-Handler

Ein angehängter Signal-Handler empfängt ein Signal von einem anhängenden Typ und nicht von dem Objekt, in dem der Handler deklariert ist.

Beispielsweise ist ` Component.onCompleted ` ein angehängter Signal-Handler. Er wird häufig verwendet, um JavaScript-Code auszuführen, sobald der Erstellungsprozess abgeschlossen ist. Hier ein Beispiel:

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)
    }
}

Der Handler „ onCompleted “ reagiert nicht auf ein „ completed “-Signal vom Typ „ Rectangle “. Stattdessen wurde ein Objekt des Anbindungstyps „ Component “ mit einem „ completed “-Signal automatisch von der QML-Engine an das Objekt „ Rectangle “ angehängt. Die Engine gibt dieses Signal aus, wenn das Rectangle-Objekt erstellt wird, und löst so den Signal-Handler „ Component.onCompleted “ aus.

Durch angehängte Signal-Handler können Objekte über bestimmte Signale benachrichtigt werden, die für jedes einzelne Objekt von Bedeutung sind. Gäbe es beispielsweise keinen angehängten Signal-Handler „ Component.onCompleted “, könnte ein Objekt diese Benachrichtigung nicht erhalten, ohne sich für ein spezielles Signal von einem bestimmten Objekt zu registrieren. Der Mechanismus der angehängten Signal-Handler ermöglicht es Objekten, bestimmte Signale ohne zusätzlichen Code zu empfangen.

Weitere Informationen zu angehängten Signalhandlern finden Sie unter „Angehängte Eigenschaften und angehängte Signalhandler “.

Hinzufügen von Signalen zu benutzerdefinierten QML-Typen

Signale können benutzerdefinierten QML-Typen mithilfe des Schlüsselworts „ signal “ hinzugefügt werden.

Die bevorzugte Syntax zum Definieren eines neuen Signals lautet:

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

Es gibt auch eine ältere Syntax, bei der der Typ vor dem Namen steht:

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

Sie sollten die neue Syntax verwenden.

Ein Signal wird ausgelöst, indem das Signal als Methode aufgerufen wird.

Beispielsweise ist der folgende Code in einer Datei namens „ SquareButton.qml “ definiert. Das Stamm Rectangle -Objekt verfügt über ein „ activated “-Signal, das immer dann ausgelöst wird, wenn der Nachkomme „ TapHandler “ auf „ tapped “ gesetzt wird. In diesem speziellen Beispiel wird das „activated“-Signal mit den x- und y-Koordinaten des Mausklicks ausgelöst:

// SquareButton.qml
import QtQuick

Rectangle {
    id: root

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

    TapHandler {
        id: handler
        onTapped: root.activated(root.mouseXY.x, root.mouseXY.y)
        onPressedChanged: root.mouseXY = handler.point.position
    }
}

Nun können sich alle Objekte des „ SquareButton “ über einen Signal-Handler für „ onActivated “ mit dem Signal „ activated “ verbinden:

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

Weitere Informationen zum Erstellen von Signalen für benutzerdefinierte QML-Typen finden Sie unter „Signalattribute “.

Signale mit Methoden und Signalen verbinden

Signalobjekte verfügen über die Methode „ connect() “, mit der ein Signal entweder an eine Methode oder an ein anderes Signal angeschlossen werden kann. Wenn ein Signal an eine Methode angeschlossen ist, wird die Methode automatisch aufgerufen, sobald das Signal ausgesendet wird. Dieser Mechanismus ermöglicht es, dass ein Signal von einer Methode anstelle eines Signal-Handlers empfangen wird.

Im folgenden Beispiel wird das Signal „ messageReceived “ mithilfe der Methode „ connect() “ mit drei Methoden verbunden:

import QtQuick

Rectangle {
    id: relay

    signal messageReceived(person: string, notice: string)

    Component.onCompleted: {
        relay.messageReceived.connect(sendToPost)
        relay.messageReceived.connect(sendToTelegraph)
        relay.messageReceived.connect(sendToEmail)
        relay.messageReceived("Tom", "Happy Birthday")
    }

    function sendToPost(person: string, notice: string) {
        console.log(`Sending to post: ${person}, ${notice}`)
    }
    function sendToTelegraph(person: string, notice: string) {
        console.log(`Sending to telegraph: ${person}, ${notice}`)
    }
    function sendToEmail(person: string, notice: string) {
        console.log(`Sending to email: ${person}, ${notice}`)
    }
}

In vielen Fällen reicht es aus, Signale über Signal-Handler zu empfangen, anstatt die Funktion `connect()` zu verwenden. Die Verwendung der Methode ` connect ` ermöglicht es jedoch, wie zuvor gezeigt, dass ein Signal von mehreren Methoden empfangen wird, was mit Signal-Handlern nicht möglich wäre, da diese eindeutig benannt sein müssen. Außerdem ist die Methode ` connect ` nützlich, wenn Signale mit dynamisch erstellten Objekten verbunden werden sollen.

Es gibt eine entsprechende Methode ` disconnect() ` zum Entfernen verbundener Signale:

Rectangle {
    id: relay
    //...

    function removeTelegraphSignal() {
        relay.messageReceived.disconnect(sendToTelegraph)
    }
}

Signal-zu-Signal-Verbindung

Durch die Verbindung von Signalen mit anderen Signalen kann die Methode „ connect() “ verschiedene Signalketten bilden.

import QtQuick

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

    signal send()
    onSend: console.log("Send clicked")

    TapHandler {
        id: mousearea
        anchors.fill: parent
        onTapped: console.log("Mouse clicked")
    }

    Component.onCompleted: {
        mousearea.tapped.connect(send)
    }
}

Immer wenn das Signal „ tapped “ des „ TapHandler “ ausgegeben wird, wird automatisch auch das Signal „ send “ ausgegeben.

output:
    MouseArea clicked
    Send clicked

Hinweis: Verbindungen zu Funktionsobjekten bleiben bestehen, solange der Absender des Signals aktiv ist. Dieses Verhalten entspricht der 3-Argument-Version von ` QObject::connect()` in C++.

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
                        })
                    }
                }
            }
        }
    }
}

In dem oben genannten Beispiel besteht das Ziel darin, die Farbe jedes geraden Rechtecks an eine globale Farbe anzupassen. Um dies zu erreichen, wird für jedes gerade Rechteck eine Verbindung zwischen dem Signal `globalColorChanged` und einer Funktion hergestellt, die die Farbe des Rechtecks festlegt. Dies funktioniert wie erwartet, solange die Rechtecke aktiv sind. Sobald jedoch die Schaltfläche „Clear“ gedrückt wird, sind die Rechtecke verschwunden, doch die Funktion, die das Signal verarbeitet, wird weiterhin jedes Mal aufgerufen, wenn das Signal ausgelöst wird. Dies lässt sich an den Fehlermeldungen erkennen, die von der Funktion ausgegeben werden, die beim Ändern der globalen Farbe im Hintergrund ausgeführt werden will.

In der aktuellen Konfiguration würden die Verbindungen erst dann aufgelöst werden, wenn das Element, das „globalColor“ enthält, zerstört wird. Um zu verhindern, dass die Verbindungen weiterbestehen, können sie beim Zerstören der Rechtecke explizit getrennt werden.

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.