【2025年版】Qt Item.activeFocus 最新情報とプログラミングテクニック

2025-06-01

「Item.activeFocus」は、Qt Quick (QML) における Item 型のプロパティの一つです。このプロパティは、その Item が現在、アクティブフォーカスを持っているかどうかを示す真偽値(ブール値)を返します。

より具体的に説明すると、

  • Item.activeFocusfalse の場合、その Item は現在アクティブフォーカスを持っていない、つまりキーボード入力などのイベントを受け取らない状態であることを意味します。

  • Item.activeFocustrue の場合、その Item は現在アクティブフォーカスを持っている、つまりキーボード入力などのイベントを受け取る状態にあることを意味します。

  • アクティブフォーカス (active focus) とは、キーボード入力などのイベントが現在、どの要素に送られるかを示す状態のことです。ユーザーがキーボードを操作した際、アクティブフォーカスを持つ要素がその入力を受け取ります。

このプロパティは、主に以下の目的で使用されます。

  • フォーカスの制御
    focus: true プロパティと組み合わせて、特定の Item にプログラム的にフォーカスを移動させたり、現在のフォーカスの状態を確認したりするために使用されます。

  • キーボードイベントの処理
    特定の Item がアクティブフォーカスを持っている場合にのみ、キーボードイベントを処理するように制御するために使用されます。

  • UIの状態管理
    アクティブフォーカスを持つ要素に応じて、UIの見た目や振る舞いを変更するために使用されます。例えば、フォーカスが当たっているボタンの色を変えたり、テキスト入力フィールドにカーソルを表示したりすることができます。


Rectangle {
    width: 100
    height: 50
    color: activeFocus ? "lightblue" : "lightgray" // アクティブフォーカスがあれば水色、なければ灰色
    focus: true // このItemがフォーカスを受け取れるようにする

    Text {
        anchors.centerIn: parent
        text: "Button"
    }

    onActiveFocusChanged: {
        if (activeFocus) {
            console.log("Button has active focus.")
        } else {
            console.log("Button lost active focus.")
        }
    }

    Keys.onPressed: {
        console.log("Key pressed on button: " + event.text)
    }
}

TextInput {
    width: 200
    height: 30
    focus: true // 初期状態でこのTextInputがフォーカスを持つ
}

この例では、RectangleTextInput の両方に focus: true が設定されています。

  • TextInput は初期状態でアクティブフォーカスを持っています。ユーザーが Rectangle をクリックするなどしてフォーカスを移動させると、RectangleactiveFocustrue になり、TextInputactiveFocusfalse になります。

  • Rectangle は、activeFocus プロパティの値に応じて背景色が変わります。また、onActiveFocusChanged シグナルハンドラで、フォーカスが変更された際にコンソールにメッセージが出力されます。さらに、Keys.onPressed ハンドラで、この Rectangle がアクティブフォーカスを持っている場合に押されたキーの情報が出力されます。



フォーカスが意図した要素に当たらない

  • トラブルシューティング

    • フォーカスを受け取りたい Itemfocus: true が設定されているか確認してください。
    • 親要素の focus プロパティやマウスイベントハンドラ (MouseArea など) の設定を確認し、子要素へのフォーカスを妨げていないか確認してください。
    • Tab キーを押してフォーカスの移動順を確認し、必要であれば要素の定義順を調整してください。
    • activeFocus プロパティが true になっている要素を特定するために、console.log() などでデバッグ出力を追加してください。
    • フォーカスを意図的に設定する場合は、Qt.callLater() やシグナル・スロットメカニズムを利用して、適切なタイミングで focus: true を設定してみてください。
    • focus: true が設定されていない: フォーカスを受け取りたい Itemfocus: true プロパティが設定されていない場合、その要素はフォーカスを受け取ることができません。
    • 親要素がフォーカスを遮っている: 親要素が focus: true を持っていたり、マウスイベントを適切に処理していなかったりする場合、子要素へのフォーカスが妨げられることがあります。
    • フォーカスの順序が意図通りでない: Tabキーなどでフォーカスを移動する際の順序は、QMLの要素の定義順に依存します。意図した順序になっていない場合があります。
    • 他の要素がアクティブフォーカスを奪っている: 意図せず他の要素(例えば、ポップアップや別のインタラクティブな要素)がアクティブフォーカスを取得している場合があります。

フォーカスが解除されない

  • トラブルシューティング

    • フォーカスを解除したいタイミングで、別の要素に focus: true を設定するか、フォーカスを持つ要素の focus: false を設定するロジックを追加してください。
    • lostFocus シグナルハンドラを利用して、フォーカスが失われた際の処理を実装してください。
    • モーダルなダイアログやポップアップを表示する際に、それらが閉じられた後に適切な要素にフォーカスを戻す処理を実装してください。
  • 原因

    • フォーカスを解除するロジックが実装されていない: 特定の操作後にフォーカスを別の要素に移す、あるいはフォーカスを解除する処理が記述されていない場合があります。
    • フォーカスを持つ要素が暗黙的にフォーカスを保持している: 一部の要素(例えば、TextInput など)は、明示的にフォーカスを解除しない限り、フォーカスを持ち続けます。

activeFocusChanged シグナルが期待通りに動作しない

  • トラブルシューティング

    • onActiveFocusChanged の記述に誤りがないか、スペルミスがないか確認してください。
    • console.log() などで、activeFocusChanged シグナルが実際に発行されているか、またその際の activeFocus の値を確認してください。
    • イベントフィルターを使用している場合は、その処理が activeFocusChanged シグナルの伝播に影響を与えていないか確認してください。
  • 原因

    • シグナルハンドラが正しく接続されていない: onActiveFocusChanged ハンドラが Item に正しく記述されていない、またはスペルミスがある可能性があります。
    • フォーカスが実際には変更されていない: UIの見た目上は変化がないように見えても、内部的にはフォーカスが移動している場合があります。デバッグ出力を追加して、実際に activeFocus の値が変化しているか確認してください。
    • 親要素や他の要素がシグナルの伝播を妨げている: イベントフィルターなどを使用している場合、シグナルが適切に伝播しないことがあります。

キーボードイベントが意図した要素で処理されない

  • トラブルシューティング

    • どの要素が現在アクティブフォーカスを持っているか (activeFocus プロパティを確認) を確認してください。
    • Keys アタッチオブジェクトが、キーボードイベントを処理したい Item の直下に記述されているか確認してください。
    • Keys.focus プロパティが true に設定されているか確認してください。
    • より複雑なキーボードイベント処理が必要な場合は、KeyEvent オブジェクトの詳細 (event.keyevent.modifiers など) を console.log() で出力して確認してください。
  • 原因

    • アクティブフォーカスを持つ要素が間違っている: キーボードイベントを受け取りたい要素がアクティブフォーカスを持っていない可能性があります。
    • Keys アタッチオブジェクトの設定ミス: Keys.onPressedKeys.onReleased などのハンドラが、イベントを処理したい Item に正しくアタッチされていない可能性があります。
    • Keys.focus プロパティの設定ミス: Keys.focusfalse になっている場合、その要素はキーボードイベントを受け取りません。
    • イベントのスコープの問題: Keys アタッチオブジェクトが配置されているスコープによっては、意図した要素にイベントが届かないことがあります。

一般的なトラブルシューティングのヒント

  • シンプルな例で検証
    問題が複雑な場合に、最小限のコードで問題を再現できる簡単な例を作成し、そこで動作を確認することで、原因を特定しやすくなります。
  • ドキュメントの参照
    Qt の公式ドキュメントは、各プロパティやシグナルの詳細な動作について解説しています。困った場合は、まずドキュメントを参照することをお勧めします。
  • Qt Creator のデバッガ
    Qt Creator のデバッガを使用すると、プロパティの値の変化をリアルタイムに監視したり、ブレークポイントを設定してコードの実行を一時停止したりすることができます。
  • デバッグ出力の活用
    console.log() を積極的に使用して、activeFocus の値の変化やシグナルの発行状況などを確認することが重要です。


例1: フォーカスに応じた背景色の変化

この例では、Rectangle がフォーカスを持つと背景色が変わります。

import QtQuick 2.0

Rectangle {
    id: root
    width: 200
    height: 100
    color: activeFocus ? "lightgreen" : "lightgray" // activeFocus が true なら明るい緑、そうでなければ灰色
    border.color: "black"
    border.width: 1
    focus: true // この Rectangle がフォーカスを受け取れるようにする

    Text {
        anchors.centerIn: parent
        text: "Click or Tab to Focus"
    }

    // activeFocus プロパティが変更されたときに実行される
    onActiveFocusChanged: {
        if (activeFocus) {
            console.log("Rectangle gained focus.")
        } else {
            console.log("Rectangle lost focus.")
        }
    }

    // キーが押されたときに実行される (activeFocus が true の場合のみ)
    Keys.onPressed: {
        console.log("Key pressed on Rectangle: " + event.text)
    }

    MouseArea {
        anchors.fill: parent
        onClicked: root.forceActiveFocus() // クリックでこの Rectangle にフォーカスを強制的に設定
    }
}

解説

  • MouseArea: Rectangle 全体を覆うマウス感知エリアです。onClicked ハンドラ内で root.forceActiveFocus() を呼び出すことで、マウスをクリックすると強制的にこの Rectangle にフォーカスが設定されます。
  • Keys.onPressed: この Rectangle がアクティブフォーカスを持っているときにキーが押されると呼び出されるハンドラです。
  • onActiveFocusChanged: activeFocus プロパティの値が変化したときに呼び出されるシグナルハンドラです。ここでは、フォーカスを得たときと失ったときにコンソールにメッセージを出力しています。
  • color: activeFocus ? "lightgreen" : "lightgray": activeFocus プロパティが true (フォーカスを持っている) の場合、背景色は "lightgreen" になり、false (フォーカスを失った) の場合は "lightgray" になります。
  • focus: true: この Rectangle はフォーカスを受け取ることができるようになります。

例2: 複数のアイテム間のフォーカス移動と視覚的なフィードバック

この例では、複数の Rectangle を作成し、フォーカスが当たっている Rectangle のボーダーの色を変えます。

import QtQuick 2.0

Column {
    spacing: 10

    Rectangle {
        id: rect1
        width: 150
        height: 50
        color: "lightblue"
        border.color: rect1.activeFocus ? "red" : "black"
        border.width: 2
        focus: true

        Text {
            anchors.centerIn: parent
            text: "Item 1"
        }
    }

    Rectangle {
        id: rect2
        width: 150
        height: 50
        color: "lightyellow"
        border.color: rect2.activeFocus ? "red" : "black"
        border.width: 2
        focus: true

        Text {
            anchors.centerIn: parent
            text: "Item 2"
        }
    }

    Rectangle {
        id: rect3
        width: 150
        height: 50
        color: "lightcoral"
        border.color: rect3.activeFocus ? "red" : "black"
        border.width: 2
        focus: true

        Text {
            anchors.centerIn: parent
            text: "Item 3"
        }
    }
}

解説

  • border.color: rect.activeFocus ? "red" : "black": 各 Rectangle のボーダーの色は、その Rectangle がアクティブフォーカスを持っている (activeFocustrue) 場合には赤色になり、そうでない場合は黒色になります。これにより、現在どのアイテムにフォーカスが当たっているかを視覚的に示すことができます。
  • それぞれの Rectanglefocus: true が設定されているため、Tabキーなどでフォーカスを移動できます。
  • 3つの RectangleColumn レイアウト内に配置されています。

例3: TextInput でのフォーカス制御

この例では、Button をクリックすると TextInput にフォーカスを移動させます。

import QtQuick 2.0

Column {
    spacing: 10

    TextInput {
        id: inputField
        width: 200
        height: 30
        placeholderText: "Enter text here"
    }

    Button {
        text: "Focus on Input"
        onClicked: inputField.forceActiveFocus() // クリックで TextInput にフォーカスを強制的に設定
    }
}

解説

  • ButtononClicked ハンドラ内で inputField.forceActiveFocus() を呼び出すことで、ボタンがクリックされると TextInput に強制的にアクティブフォーカスが設定され、キーボード入力が可能になります。
  • TextInput はテキスト入力を受け付ける要素です。

例4: カスタムコンポーネントでのフォーカス処理

カスタムコンポーネント内で activeFocus を使用して、内部の状態を管理する例です。

import QtQuick 2.0

Item {
    id: customButton
    width: 100
    height: 30
    focus: true

    Rectangle {
        anchors.fill: parent
        color: customButton.activeFocus ? "orange" : "gray"
        border.color: "black"
        border.width: 1

        Text {
            anchors.centerIn: parent
            text: "Custom Button"
        }

        MouseArea {
            anchors.fill: parent
            onClicked: {
                customButton.forceActiveFocus()
                console.log("Custom button clicked and focused.")
            }
        }
    }

    Keys.onPressed: {
        if (event.key === Qt.Key_Space || event.key === Qt.Key_Enter) {
            console.log("Custom button activated via keyboard.")
            // ここでボタンが押された際の処理を実行
            event.accepted = true // イベントを処理済みとしてマーク
        }
    }
}
// メインの QML ファイル
import QtQuick 2.0

Column {
    spacing: 20

    CustomButton {}
    Rectangle {
        width: 100
        height: 30
        color: "lightblue"
        border.color: "black"
        border.width: 1
        focus: true
        Text {
            anchors.centerIn: parent
            text: "Another Item"
        }
    }
}
  • Keys.onPressed ハンドラ内で、スペースキーまたはエンターキーが押された場合に特定の処理を実行し、event.accepted = true でイベントを処理済みとしてマークしています。これにより、親要素などが同じキーイベントを再度処理することを防ぎます。
  • MouseAreaonClicked ハンドラで customButton.forceActiveFocus() を呼び出すことで、クリック時にフォーカスを設定します。
  • 内部の Rectangle の色は、customButton.activeFocus の値に応じて変化します。
  • focus: true を設定することで、このカスタムコンポーネント自体がフォーカスを受け取れるようになります。
  • CustomButton は、Item をベースとしたカスタムコンポーネントです。


focus プロパティとシグナルハンドラ (focusChanged) の利用

Item 型には activeFocus と似た focus プロパティがあり、これはその Item がフォーカスを受け取ることができる状態かどうかを示します。focus: true を設定することで、その Item はフォーカスを受け取る候補となります。また、フォーカスの状態が変化した際には focusChanged シグナルが発行されます。

Rectangle {
    id: focusableRect
    width: 100
    height: 50
    color: focusableRect.focus ? "yellow" : "gray"
    focus: true

    Text {
        anchors.centerIn: parent
        text: "Focusable"
    }

    onFocusChanged: {
        if (focus) {
            console.log("Rectangle gained focus (via 'focus' property).")
        } else {
            console.log("Rectangle lost focus (via 'focus' property).")
        }
    }

    MouseArea {
        anchors.fill: parent
        onClicked: focusableRect.forceActiveFocus()
    }
}

解説

  • onFocusChanged: focus プロパティの値が変化したときに呼び出されるシグナルハンドラです。フォーカスを得たときと失ったときにメッセージを出力しています。
  • color: focusableRect.focus ? "yellow" : "gray": focus プロパティが true の場合(必ずしもアクティブフォーカスを持っているとは限りませんが、フォーカスを受け取れる状態)、背景色を黄色にしています。
  • focus: true: この Rectangle はフォーカスを受け取れるようになります。

activeFocus は、実際にキーボード入力などを受け取っているかどうかという「現在のアクティブなフォーカス状態」を示すのに対し、focus は「フォーカスを受け取ることができる能力」を示すという点で異なります。しかし、視覚的なフィードバックや、フォーカスを得た/失った際の処理を実装する際には、focus プロパティと focusChanged シグナルも有効な代替手段となります。

Qt.inputMethod.requestFocus() と Qt.inputMethod.releaseFocus()

これらの静的関数を使用すると、プログラム的に特定の Item にアクティブフォーカスを設定したり、解除したりすることができます。これは、例えば特定のイベントが発生した際に、特定の入力フィールドに強制的にフォーカスを移したい場合などに便利です。

import QtQuick 2.0

Column {
    spacing: 10

    TextInput {
        id: input1
        width: 200
        height: 30
        placeholderText: "Input 1"
    }

    TextInput {
        id: input2
        width: 200
        height: 30
        placeholderText: "Input 2"
    }

    Button {
        text: "Focus Input 2"
        onClicked: Qt.inputMethod.requestFocus(input2)
    }

    Button {
        text: "Release Focus from Input 2"
        onClicked: Qt.inputMethod.releaseFocus(input2)
    }
}

解説

  • Qt.inputMethod.releaseFocus(input2): ボタンがクリックされると、input2 からアクティブフォーカスが解除されます。
  • Qt.inputMethod.requestFocus(input2): ボタンがクリックされると、input2 にアクティブフォーカスが設定されます。

この方法は、focus: true を事前に設定しておき、特定のタイミングでアクティブフォーカスを制御したい場合に有効です。

Keys アタッチオブジェクトの focus プロパティとハンドラ

Keys アタッチオブジェクトを使用すると、特定のキーイベントが発生した際に、プログラム的にフォーカスを移動させることができます。Keys.focus プロパティを true に設定することで、その Item がキーイベントを監視し、ハンドラ内でフォーカスを操作できます。

import QtQuick 2.0

Item {
    id: rootItem
    width: 200
    height: 150
    focus: true // Item 自体がフォーカスを受け取れるようにする

    Rectangle {
        id: rectA
        width: 80
        height: 50
        color: rootItem.activeFocus && currentFocus === rectA ? "lightblue" : "lightgray"
        border.color: "black"
        border.width: 1
        anchors.top: parent.top
        anchors.left: parent.left

        Text {
            anchors.centerIn: parent
            text: "A"
        }
    }

    Rectangle {
        id: rectB
        width: 80
        height: 50
        color: rootItem.activeFocus && currentFocus === rectB ? "lightgreen" : "lightgray"
        border.color: "black"
        border.width: 1
        anchors.top: parent.top
        anchors.right: parent.right

        Text {
            anchors.centerIn: parent
            text: "B"
        }
    }

    property var currentFocus: rectA // 現在フォーカスを持っている要素を追跡

    Keys.onTabPressed: {
        if (currentFocus === rectA) {
            currentFocus = rectB;
            rectB.forceActiveFocus();
        } else if (currentFocus === rectB) {
            currentFocus = rectA;
            rectA.forceActiveFocus();
        }
        event.accepted = true;
    }
}

解説

  • event.accepted = true: Tabキーのデフォルトのフォーカス移動の動作を抑制します。
  • currentFocus プロパティで現在フォーカスを持っている要素を追跡し、Tabキーが押されるたびに forceActiveFocus() を使ってフォーカスを別の Rectangle に移動させています。
  • Keys.onTabPressed: Tabキーが押されたときに呼び出されるハンドラです。
  • rootItemfocus: true を設定し、キーイベントを受け取れるようにします。

この方法は、特定のキー入力に応じて、アプリケーション独自のフォーカス移動ロジックを実装する場合に非常に柔軟性があります。

カスタムフォーカス管理ロジックの実装

より複雑なUIや、特定のフォーカス移動ルールが必要な場合には、独自のフォーカス管理ロジックを実装することも可能です。これには、フォーカス可能な要素のリストを保持し、特定のイベント(キープレス、マウス操作など)に応じて、プログラム的に次のフォーカス要素を決定し、forceActiveFocus() を呼び出すといった処理が含まれます。

このアプローチは、標準的なフォーカス管理の仕組みでは実現できない、高度なカスタマイズが必要な場合に採用されます。

Item.activeFocus は現在のフォーカス状態を直接的に示す便利なプロパティですが、フォーカスの制御や視覚的なフィードバックの実現には、

  • カスタムのフォーカス管理ロジック
  • Keys アタッチオブジェクトの focus プロパティとハンドラ
  • Qt.inputMethod.requestFocus()Qt.inputMethod.releaseFocus()
  • focus プロパティと focusChanged シグナル