このページでは

キーボードのフォーカスQt Quick

キーが押されたり離されたりすると、キーイベントが生成され、フォーカスされているQt Quick Item に配信されます。再利用可能なコンポーネントの構築を容易にし、流動的なユーザーインターフェースに特有のいくつかのケースに対応するため、Qt Quick の各項目は、Qtの従来のキーボードフォーカスモデルにスコープベースの拡張機能を追加しています。

キー処理の概要

ユーザーがキーを押下または離すと、以下の処理が行われます:

  1. Qt はキー操作を受け取り、キーイベントを生成します。
  2. QQuickWindow がアプリケーションのfocus window である場合、キーイベントはその に配信されます。
  3. キーイベントは、シーンによってアクティブなフォーカスを持つItem に配信されます。アクティブなフォーカスを持つアイテムがない場合、キーイベントは無視されます。
  4. アクティブなフォーカスを持つQQuickItem がキーイベントを受け入れると、伝播は停止します。そうでない場合、イベントは、イベントが受け入れられるか、ルートアイテムに到達するまで、 の親に送信されます。

    以下の例で、アクティブなフォーカスを持つRectangle 型がA キーを押された場合、イベントはそれ以上伝播されません。B キーを押すと、イベントはルートアイテムまで伝播され、その結果無視されます。

    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. ルートItem に到達した場合、キーイベントはignored となり、通常のQtキー処理が継続されます。

Keys attached property およびKeyNavigation attached property も参照してください。

アクティブなフォーカス項目の取得

Item がアクティブなフォーカスを持っているかどうかは、Item::activeFocus プロパティを通じて照会できます。たとえば、ここでは、アクティブなフォーカスの有無によってテキストが決まるText タイプがあります。

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

フォーカスの取得とフォーカススコープ

Item は、focus プロパティをtrue に設定することでフォーカスを要求します。

非常に単純なケースでは、単にfocus プロパティを設定するだけで十分な場合もあります。qmlツールで次の例を実行すると、keyHandler タイプがアクティブなフォーカスを持ち、A 、B 、またはC キーを押すとテキストが適切に変更されることがわかります。

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

キー「C」が押されたことを示す、青い丸いウィジェット

しかし、上記の例を再利用可能なコンポーネントやインポートされたコンポーネントとして使用する場合、focus プロパティをこのように単純に使用するだけでは不十分になります。

これを実証するために、以前に定義したコンポーネントのインスタンスを2つ作成し、最初のインスタンスにフォーカスを設定します。目的は、A 、B 、またはC キーが押された際、2つのコンポーネントのうち最初のものがイベントを受け取り、それに応じて反応するようにすることです。

MyWidgetをインポートし、2つのインスタンスを作成するコード:

//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"
        }
    }
}

MyWidgetのコード:

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

最初のMyWidget オブジェクトにフォーカスを当てたいので、そのfocus プロパティをtrue に設定しています。しかし、コードを実行すると、2番目のウィジェットにフォーカスが移ってしまうことがあります。

2つのウィジェットが積み重なっており、2番目の緑色のウィジェットにはキーAが押されたことが表示されている

MyWidget とwindow の両方のコードを確認すると、問題は明らかです。focus プロパティをtrue に設定しているタイプが3つ存在します。2つのMyWidgetはfocus をtrue に設定しており、window コンポーネントもフォーカスを設定しています。 最終的に、キーボードフォーカスを持つことができるのは1つのタイプのみであり、システムがどのタイプにフォーカスを与えるかを決定する必要があります。QMLでは、どの要素のプロパティが最初に初期化されるかは保証されていないため、最後に読み込まれたMyWidget が初期フォーカスを得る可能性があります。

この問題は可視性に起因しています。MyWidget コンポーネントはフォーカスを取得したいと考えていますが、インポートまたは再利用される際にはフォーカスを制御することができません。同様に、window コンポーネントも、そのインポートされたコンポーネントがフォーカスを要求しているかどうかを知る手段を持っていません。

この問題を解決するため、QMLでは「フォーカススコープ」と呼ばれる概念が導入されています。既存のQtユーザーにとって、フォーカススコープは自動的なフォーカスプロキシのようなものです。フォーカススコープは、FocusScope 型を宣言することで作成されます。

次の例では、コンポーネントに `FocusScope ` 型が追加され、その視覚的な結果が示されています。

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

2つのウィジェットが積み重なっており、上段の青いウィジェットには「Key B」が押されたことが表示されている

概念的には、フォーカススコープは非常に単純です。

  • 各フォーカススコープ内では、1つのオブジェクトに対してItem::focus をtrue に設定できます。複数のItem でfocus プロパティが設定されている場合、focus を最後に設定したタイプがフォーカスを受け、他のタイプはフォーカスが解除されます。これは、フォーカススコープが存在しない場合と同様です。
  • フォーカススコープがアクティブなフォーカスを受け取ると、focus が設定されている(存在する場合)その中に含まれるタイプもアクティブなフォーカスを受け取ります。このタイプがFocusScope である場合、プロキシ動作は継続します。フォーカススコープとサブフォーカス対象項目の両方にactiveFocus プロパティが設定されます。

なお、FocusScope 型はビジュアル型ではないため、その子要素のプロパティをFocusScope の親アイテムに公開する必要があります。レイアウトおよび配置タイプは、これらのビジュアルプロパティやスタイルプロパティを使用してレイアウトを作成します。この例では、FocusScope に独自のビジュアルプロパティがないため、Column 型は2つのウィジェットを正しく表示できません。 MyWidgetコンポーネントは、rectangle のプロパティに直接バインドすることで、Column タイプがFocusScope の子要素を含むレイアウトを作成できるようにしています。

これまでの例では、2番目のコンポーネントが静的に選択された状態になっています。このコンポーネントをクリック可能に拡張し、元のアプリケーションに追加するのは、もはや簡単な作業です。依然として、デフォルトではいずれかのウィジェットにフォーカスを当てています。これで、どちらかのMyClickableWidgetをクリックすると、そのウィジェットにフォーカスが移り、もう一方のウィジェットはフォーカスを失います。

2つの MyClickableWidget インスタンスをインポートして作成するコード:

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

}

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

それぞれ、最後に押されたキーを表示するクリック可能なウィジェットが2つ

QMLのItem が明示的にフォーカスを解放した場合(アクティブなフォーカスを持っている間にfocus プロパティをfalse に設定することで)、システムは自動的に別のタイプをフォーカス対象として選択しません。つまり、現在アクティブなフォーカスが存在しない状態になる可能性があります。

FocusScope タイプを使用して複数の領域間でキーボードフォーカスを移動させるデモについては、「Qt Quick の例 - キー操作」を参照してください。

フォーカススコープの高度な活用法

フォーカススコープを使用すると、フォーカスの割り当てを簡単に分割できます。いくつかの QML アイテムは、この目的でフォーカススコープを利用しています。

ListView例えば、`ListView ` 自体が一つのフォーカススコープです。通常、` ` には手動で追加された視覚的な子要素がないため、このことは目立ちません。フォーカススコープであることで、`ListView ` は、アプリケーションの他の部分にどのような影響を与えるかを気にすることなく、現在のリスト項目にフォーカスを当てることができます。これにより、現在の項目のデリゲートがキー入力に反応できるようになります。

この人工的な例は、その仕組みを示しています。「Return 」キーを押すと、現在のリスト項目の名前が出力されます。

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

編集可能な名前が3つ記載されたリスト:ボブ、ジョン、マイケル

この例は単純ですが、その裏では多くの処理が行われています。現在の項目が変更されるたびに、ListView はデリゲートのItem::focus プロパティを設定します。ListView はフォーカススコープであるため、これはアプリケーションの他の部分には影響を与えません。ただし、ListView 自体がアクティブなフォーカスを持っている場合、これによりデリゲート自体もアクティブなフォーカスを受け取ることになります。 この例では、デリゲートのルート型もフォーカススコープであるため、その結果、Return キーの処理を実際に実行するTextInput 型にアクティブなフォーカスが与えられます。

PathView やGridView など、すべてのQMLビュークラスは、それぞれのデリゲートでキー処理が可能になるよう、同様の挙動を示します。

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