Auf dieser Seite

Tastaturfokus in Qt Quick

Wenn eine Taste gedrückt oder losgelassen wird, wird ein Tastenereignis generiert und an das Element mit Fokus Qt Quick Item übermittelt. Um die Erstellung wiederverwendbarer Komponenten zu erleichtern und einige der für flüssige Benutzeroberflächen spezifischen Fälle zu berücksichtigen, erweitern die Elemente „ Qt Quick “ das traditionelle Tastaturfokusmodell von Qt XML um eine bereichsbasierte Erweiterung.

Übersicht über die Tastenverarbeitung

Wenn der Benutzer eine Taste drückt oder loslässt, geschieht Folgendes:

  1. Qt empfängt die Tastenaktion und generiert ein Tastenereignis.
  2. Ist ein „ QQuickWindow “ der „ focus window “ der Anwendung, wird das Tastenereignis an diesen weitergeleitet.
  3. Das Tastenereignis wird von der Szene an das „ Item “ mit aktivem Fokus weitergeleitet. Hat kein Element den aktiven Fokus, wird das Tastenereignis ignoriert.
  4. Wenn das „ QQuickItem “ mit aktivem Fokus das Tastenereignis akzeptiert, wird die Weiterleitung gestoppt. Andernfalls wird das Ereignis an das übergeordnete Element des „Item“ gesendet, bis das Ereignis akzeptiert wird oder das Stammelement erreicht ist.

    Wenn das „ Rectangle “-Element im folgenden Beispiel den aktiven Fokus hat und die Taste „ A “ gedrückt wird, wird das Ereignis nicht weiter weitergeleitet. Beim Drücken der Taste „ B “ wird das Ereignis an das Stammelement weitergeleitet und somit ignoriert.

    Rectangle {
        width: 100; height: 100
        focus: true
        Keys.onPressed: (event)=> {
            if (event.key == Qt.Key_A) {
                console.log('Key A was pressed');
                event.accepted = true;
            }
        }
    }
  5. Wird das Stamm- Item erreicht, handelt es sich bei dem Tastenereignis um „ ignored “, und die reguläre Qt-Tastenverarbeitung wird fortgesetzt.

Siehe auch „ Keys attached property “ und „ KeyNavigation attached property “.

Abfrage des aktiven Fokuselements

Ob ein „ Item “ den aktiven Fokus hat oder nicht, lässt sich über die Eigenschaft „ Item::activeFocus “ abfragen. Hier haben wir beispielsweise einen Typ „ Text “, dessen Text davon abhängt, ob er den aktiven Fokus hat oder nicht.

    Text {
        text: activeFocus ? "I have active focus!" : "I do not have active focus"
    }

Fokus und Fokusbereiche erlangen

Ein „ Item “ fordert den Fokus an, indem die Eigenschaft „ focus “ auf „ true “ gesetzt wird.

In sehr einfachen Fällen reicht es manchmal aus, lediglich die Eigenschaft „ focus “ zu setzen. Wenn wir das folgende Beispiel mit dem qml-Tool ausführen, sehen wir, dass der Typ „ keyHandler “ den aktiven Fokus hat und das Drücken der Tasten „ A “, „ B “ oder „ C “ den Text entsprechend ändert.

Rectangle {
    color: "lightsteelblue"; width: 240; height: 25
    Text { id: myText }
    Item {
        id: keyHandler
        focus: true
        Keys.onPressed: (event)=> {
            if (event.key == Qt.Key_A)
                myText.text = 'Key A was pressed'
            else if (event.key == Qt.Key_B)
                myText.text = 'Key B was pressed'
            else if (event.key == Qt.Key_C)
                myText.text = 'Key C was pressed'
        }
    }
}

Blaues, abgerundetes Widget, das anzeigt, dass die Taste C gedrückt wurde

Sollte das obige Beispiel jedoch als wiederverwendbare oder importierte Komponente verwendet werden, reicht diese einfache Verwendung der Eigenschaft „ focus “ nicht mehr aus.

Zur Veranschaulichung erstellen wir zwei Instanzen unserer zuvor definierten Komponente und weisen der ersten den Fokus zu. Damit soll erreicht werden, dass beim Drücken der Tasten „ A “, „ B “ oder „ C “ die erste der beiden Komponenten das Ereignis empfängt und entsprechend reagiert.

Der Code, der zwei MyWidget-Instanzen importiert und erstellt:

//Window code that imports MyWidget
Rectangle {
    id: window
    color: "white"; width: 240; height: 150

    Column {
        anchors.centerIn: parent; spacing: 15

        MyWidget {
            focus: true             //set this MyWidget to receive the focus
            color: "lightblue"
        }
        MyWidget {
            color: "palegreen"
        }
    }
}

Der MyWidget-Code:

Rectangle {
    id: widget
    color: "lightsteelblue"; width: 175; height: 25; radius: 10; antialiasing: true
    Text { id: label; anchors.centerIn: parent}
    focus: true
    Keys.onPressed: (event)=> {
        if (event.key == Qt.Key_A)
            label.text = 'Key A was pressed'
        else if (event.key == Qt.Key_B)
            label.text = 'Key B was pressed'
        else if (event.key == Qt.Key_C)
            label.text = 'Key C was pressed'
    }
}

Wir möchten, dass das erste „ MyWidget “-Objekt den Fokus hat, daher setzen wir seine Eigenschaft „ focus “ auf „ true “. Beim Ausführen des Codes kann es jedoch vorkommen, dass das zweite Widget den Fokus erhält.

Zwei übereinander angeordnete Widgets, wobei das zweite, grüne Widget anzeigt, dass die Taste A gedrückt wurde

Betrachtet man sowohl den Code für „ MyWidget “ als auch den für „ window “, wird das Problem deutlich: Es gibt drei Typen, die die Eigenschaft „ focus “ auf „ true “ setzen. Die beiden „ MyWidget“-Elemente setzen die Eigenschaft „ focus “ auf „ true “, und auch die Komponente „ window “ setzt den Fokus. Letztendlich kann nur ein Typ den Tastaturfokus haben, und das System muss entscheiden, welcher Typ den Fokus erhält. Da QML nicht garantiert, welches Element als Erstes initialisiert wird, kann es vorkommen, dass das letzte „ MyWidget “ den anfänglichen Fokus erhält.

Dieses Problem ist auf die Sichtbarkeit zurückzuführen. Die Komponente „ MyWidget “ möchte den Fokus haben, kann diesen jedoch nicht steuern, wenn sie importiert oder wiederverwendet wird. Ebenso hat die Komponente „ window “ keine Möglichkeit zu erkennen, ob ihre importierten Komponenten den Fokus anfordern.

Um dieses Problem zu lösen, führt QML ein Konzept ein, das als „Fokusbereich“ (focus scope) bezeichnet wird. Für bestehende Qt-Anwender ist ein Fokusbereich vergleichbar mit einem automatischen Fokus-Proxy. Ein Fokusbereich wird durch die Deklaration des Typs „ FocusScope “ erstellt.

Im folgenden Beispiel wird der Typ „ FocusScope “ zur Komponente hinzugefügt und das visuelle Ergebnis dargestellt.

FocusScope {

    //FocusScope needs to bind to visual properties of the Rectangle
    property alias color: rectangle.color
    x: rectangle.x; y: rectangle.y
    width: rectangle.width; height: rectangle.height

    Rectangle {
        id: rectangle
        anchors.centerIn: parent
        color: "lightsteelblue"; width: 175; height: 25; radius: 10; antialiasing: true
        Text { id: label; anchors.centerIn: parent }
        focus: true
        Keys.onPressed: (event)=> {
            if (event.key == Qt.Key_A)
                label.text = 'Key A was pressed'
            else if (event.key == Qt.Key_B)
                label.text = 'Key B was pressed'
            else if (event.key == Qt.Key_C)
                label.text = 'Key C was pressed'
        }
    }
}

Zwei übereinander angeordnete Widgets, wobei das erste blaue anzeigt, dass die Taste B gedrückt wurde

Konzeptionell sind Fokusbereiche recht einfach.

  • Innerhalb jedes „Focus Scope“ kann für ein Objekt die Eigenschaft „ Item::focus “ auf „ true “ gesetzt werden. Wenn bei mehr als einem „ Item “ die Eigenschaft „ focus “ gesetzt ist, erhält der Typ, bei dem „ focus “ zuletzt gesetzt wurde, den Fokus, während die anderen deaktiviert werden – ähnlich wie bei fehlenden „Focus Scopes“.
  • Wenn ein Fokusbereich den aktiven Fokus erhält, erhält auch der darin enthaltene Typ, bei dem „ focus “ gesetzt ist (falls vorhanden), den aktiven Fokus. Ist dieser Typ ebenfalls ein „ FocusScope “, setzt sich das Proxy-Verhalten fort. Sowohl der Fokusbereich als auch das untergeordnete Element erhalten die Eigenschaft „ activeFocus “.

Beachten Sie, dass der Typ „ FocusScope “ kein visueller Typ ist und daher die Eigenschaften seiner untergeordneten Elemente dem übergeordneten Element des „ FocusScope “ offengelegt werden müssen. Layout- und Positionierungstypen verwenden diese visuellen und Stil-Eigenschaften, um das Layout zu erstellen. In unserem Beispiel kann der Typ „ Column “ die beiden Widgets nicht korrekt anzeigen, da dem „ FocusScope “ eigene visuelle Eigenschaften fehlen. Die „MyWidget“-Komponente bindet sich direkt an die „ rectangle “-Eigenschaften, damit der Typ „ Column “ das Layout erstellen kann, das die untergeordneten Elemente von „ FocusScope “ enthält.

Bislang ist in dem Beispiel die zweite Komponente statisch ausgewählt. Es ist nun ein Leichtes, diese Komponente so zu erweitern, dass sie anklickbar ist, und sie der ursprünglichen Anwendung hinzuzufügen. Wir legen weiterhin fest, dass eines der Widgets standardmäßig den Fokus erhält. Wenn man nun auf eines der beiden „MyClickableWidget“-Elemente klickt, erhält dieses den Fokus, während das andere Widget den Fokus verliert.

Der Code, der zwei „MyClickableWidget“-Instanzen importiert und erstellt:

Rectangle {
    id: window

    color: "white"; width: 240; height: 150

    Column {
        anchors.centerIn: parent; spacing: 15

        MyClickableWidget {
            focus: true             //set this MyWidget to receive the focus
            color: "lightblue"
        }
        MyClickableWidget {
            color: "palegreen"
        }
    }

}

Der Code für „MyClickableWidget“:

FocusScope {

    id: scope

    //FocusScope needs to bind to visual properties of the children
    property alias color: rectangle.color
    x: rectangle.x; y: rectangle.y
    width: rectangle.width; height: rectangle.height

    Rectangle {
        id: rectangle
        anchors.centerIn: parent
        color: "lightsteelblue"; width: 175; height: 25; radius: 10; antialiasing: true
        Text { id: label; anchors.centerIn: parent }
        focus: true
        Keys.onPressed: (event)=> {
            if (event.key == Qt.Key_A)
                label.text = 'Key A was pressed'
            else if (event.key == Qt.Key_B)
                label.text = 'Key B was pressed'
            else if (event.key == Qt.Key_C)
                label.text = 'Key C was pressed'
        }
    }
    MouseArea { anchors.fill: parent; onClicked: { scope.focus = true } }
}

Zwei anklickbare Widgets, die jeweils die zuletzt gedrückte Taste anzeigen

Wenn ein QML- Item den Fokus explizit abgibt (indem es seine Eigenschaft „ focus “ auf „ false “ setzt, während es den aktiven Fokus hat), wählt das System nicht automatisch einen anderen Typ aus, der den Fokus erhält. Das heißt, es ist möglich, dass derzeit kein aktiver Fokus vorhanden ist.

Unter „Qt Quick -Beispiele – Tastaturinteraktion“ finden Sie eine Demonstration, wie der Tastaturfokus mithilfe von „ FocusScope “-Typen zwischen mehreren Bereichen verschoben werden kann.

Fortgeschrittene Anwendungen von Fokusbereichen

Fokusbereiche ermöglichen eine einfache Aufteilung der Fokuszuweisung. Mehrere QML-Elemente nutzen dies zu diesem Zweck.

ListViewBeispielsweise ist „ ListView “ selbst ein Fokusbereich. Im Allgemeinen fällt dies nicht auf, da „ ListView “ normalerweise keine manuell hinzugefügten visuellen untergeordneten Elemente enthält. Da „ “ ein Fokusbereich ist, kann es den Fokus auf das aktuelle Listenelement setzen, ohne dass Auswirkungen auf den Rest der Anwendung zu befürchten sind. Dadurch kann der Delegat des aktuellen Elements auf Tastendrücke reagieren.

Dieses konstruierte Beispiel zeigt, wie das funktioniert. Durch Drücken der Taste „ Return “ wird der Name des aktuellen Listenelements ausgegeben.

Rectangle {
    color: "lightsteelblue"; width: 100; height: 50

    ListView {
        anchors.fill: parent
        focus: true

        model: ListModel {
            ListElement { name: "Bob" }
            ListElement { name: "John" }
            ListElement { name: "Michael" }
        }

        delegate: FocusScope {
                width: childrenRect.width; height: childrenRect.height
                x:childrenRect.x; y: childrenRect.y
                TextInput {
                    focus: true
                    text: name
                    Keys.onReturnPressed: console.log(name)
                }
        }
    }
}

Liste mit drei bearbeitbaren Namen: Bob, John, Michael

Das Beispiel ist zwar einfach, hinter den Kulissen passiert jedoch einiges. Immer wenn sich das aktuelle Element ändert, setzt der „ ListView “ die „ Item::focus “-Eigenschaft des Delegaten. Da der „ ListView “ ein Fokusbereich ist, hat dies keine Auswirkungen auf den Rest der Anwendung. Hat jedoch der „ ListView “ selbst den aktiven Fokus, führt dies dazu, dass der Delegat selbst den aktiven Fokus erhält. In diesem Beispiel ist der Stammtyp des Delegaten ebenfalls ein Fokusbereich, was wiederum dem Typ „ TextInput “ den aktiven Fokus zuweist, der tatsächlich die Verarbeitung der Taste „ Return “ übernimmt.

Alle QML-Ansichtsklassen, wie beispielsweise „ PathView “ und „ GridView “, verhalten sich auf ähnliche Weise, um die Tastenbearbeitung in ihren jeweiligen Delegaten zu ermöglichen.

© 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.