Qt をはじめよう! 第18回: タブオーダーを設定しよう

前回 はアクセスキーの設定について学びました。今回はタブオーダーです。

タブオーダーとは

デスクトップで動くアプリケーションではフォーカス可能なウィジェット間を移動するために(Shift+)タブキーが使用されます。Qt ではタブキーを押した際にどのウィジェットへフォーカスを移すかを設定することが可能で、この順番をタブオーダーと呼びます。

Qt ではデザイナを使用してウィジェットを配置した場合でも、ソースコードでウィジェットを配置した場合でも、これらのウィジェットのタブオーダーは自動的に割り振られるため、あまり意識する必要はありません。
しかし、画面が複雑な場合や、後で画面のレイアウトを変更した際などに、タブオーダーがずれてしまったり、自動的に割り振られる順番が理想的ではないこともあります。今回はこのタブオーダーを明示的に指定する方法について学びましょう。

フォームの作成

タブオーダーの設定の準備として以下のようなフォームを作成しましょう。

ウィジェットの配置と設定の変更

左側のレイアウトは以下のウィジェットを FormLayout でまとめたものです。

  • Label
    • text を "Search &for" に変更
  • LineEdit
  • Label
    • text を "Replace &with" に変更
  • LineEdit
  • CheckBox
    • text を "&Case sensitive" に変更

"Search for:" と "Replace with:" では 前回 学んだ Buddy の設定もそれぞれの右側にある LineEdit に対して行っています。

右側のレイアウトは以下のウィジェットを垂直に並べたものです。

  • PushButton
    • text を "&Find" に変更
  • PushButton
    • text を "&Replace" に変更
  • ButtonBox
    • orientation を "Vertical" に変更
    • standardButtons プロパティのチェックで "OK" と "Cancel" を無効にし、"Close" を有効に変更
      上記のスクリーンショットを参考にしてください

水平に並べるレイアウトをフォーム自体に設定しこれらの2つのレイアウトを並べています。

それではプレビューを開いて動作を確認してみましょう。

プレビューの表示

上記のフォームが通常の手順で作られていた場合には、プレビューを開いた場合に "Search for" の LineEdit にフォーカスがあり、タブキーを押すと以下の順番にフォーカスが移動するはずです。

  1. "Search for:"
  2. "Replace with:"
  3. "Case sensitive"
  4. "Find"
  5. "Replace"
  6. "閉じる(C)"
  7. "Search for:" (1番目に戻る)

もしこの順番になっていなかった場合は、一度レイアウトを全て解除してから再度レイアウトを設定してみてください。それでも上記の通りの順番にならない場合があるかもしれませんが、この後タブオーダーを設定しますのでここでは問題ありません。とりあえず次に進んでください。

Mac の場合にはデフォルトでは上記のうち LineEdit のみがフォーカスの対象になります。タブキーを押した際に PushButton や CheckButton にもフォーカスが移るようにする場合は Mac の「システム環境設定」→「キーボード」を開き、「キーボードショットカット」タブの「フルキーボードアクセス」の設定を "すべてのコントロール" に変更してください。

フルキーボードアクセスの設定

タブオーダーの設定

タブオーダーの設定の方法を学ぶため、一度見た目の順番とは異なる不自然な状態を作ってみましょう。
はじめに、上記で作成したフォームから "Search For" 用の LineEdit を削除します。この LineEdit を選択し「Del」キーか「Backspace」キー、もしくはそれに相当するキーを押してください。ウィジェットの削除はメニューの「編集」→「削除」やコンテキストメニューの「削除」でも可能です。

LineEdit を削除

次に、左側のウィジェットペインから "Search for" の LineEdit があった場所に再度 LineEdit をドラッグ&ドロップで追加します。この際、レイアウトの解除は行わずに、このレイアウト(FormLayout)の "Search for:" のラベルの右側のスペースにドロップしてください。

LineEdit をドラッグ&ドロップでレイアウトに追加

LineEdit が元々の位置に再度追加されました

それではプレビューで確認してみましょう。この場合は始めは "Replace with:" の LineEdit にフォーカスがあり、タブキーを押すと以下の順番でフォーカスが移っていきます。

  1. "Replace with:"
  2. "Case sensitive"
  3. "Search for:"
  4. "Find"
  5. "Replace"
  6. "閉じる(C)"
  7. "Replace with:" (1番目に戻る)

このように、適用済みのレイアウトにウィジェットを後から追加した場合にはタブオーダーが見た目通りに設定されない状態になることがあります。また、画面のレイアウトが複雑な場合には、自動的に設定される順番が必ずしも適切ではないこともあります。

それでは、この状態のフォームにタブオーダーを変更するための設定をしましょう。デザイナ上部の「タブ順序を編集」ボタンをクリックすると、タブオーダーの編集状態に移行します。

「タブ順序の編集」をクリック

フォーカスを持つ各ウィジェットの左上に青色の四角の中に数字が表示されます。この数字はウィジェットがフォームに配置された順に振られた数字です。このため、ウィジェットを配置した順によってはこの青い番号は上記のスクリーンショット内の番号と完全に一致しないことがありますが、これは問題ありません。また、この番号はフォームにレイアウトが全く設定されていない場合にはタブオーダーと一致しますが、レイアウトが設定されている場合には必ずしもタブオーダーとは一致しません。

それでは、タブオーダーを設定しましょう。各ウィジェットの数字を順番にクリックすることでタブオーダーの設定をすることが可能です。

左上の LineEdit の数字をクリック

順番に数字をクリック

直前にタブオーダーを設定したウィジェットの数字は赤色の四角で、それより前に設定済みのウィジェットの数字は緑色の四角で表示されます。

全てのウィジェットの数字を順番にクリックし、タブオーダーの設定が終わったら、プレビューを表示し確認してみましょう。タブキーを押す毎に設定した通りの順番でフォーカスが移るはずです。

タブオーダーの設定中に順番を間違えた場合のためにコンテキストメニューでいくつかの機能を提供しています。

右クリックでコンテキストメニューを表示

「この番号から設定」はどれか数字の上でコンテキストメニューを表示した場合に有効になり、その番号以降に設定されている順番をクリアし、その番号から再度設定し直すことができます。
「1番から設定」をクリックすると、すべての設定をクリアし、最初からやり直すことができます。
「タブ順のリスト…」を選択すると一覧画面で順番の編集をすることが可能です。

タブ順のリスト画面

タブオーダー設定の仕組み

アクセスキーの設定 同様、タブオーダーの設定も ui ファイルに保存されます。「編集」ボタンをクリックし、ui ファイルのソースの中に以下の設定が含まれていることを確認してみてください。

<tabstops>
<tabstop>lineEdit</tabstop>
<tabstop>lineEdit_2</tabstop>
<tabstop>checkBox</tabstop>
<tabstop>pushButton</tabstop>
<tabstop>pushButton_2</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>

ui_widget.h に含まれる setupUi() メソッドもこれを受けて以下のコードが生成されます。

        QWidget::setTabOrder(lineEdit, lineEdit_2);
QWidget::setTabOrder(lineEdit_2, checkBox);
QWidget::setTabOrder(checkBox, pushButton);
QWidget::setTabOrder(pushButton, pushButton_2);
QWidget::setTabOrder(pushButton_2, buttonBox);

[qt QWidget setTabOrder] は2つのウィジェットのポインタを引数(first, second)に持ち、first の次のウィジェットを second で指定しタブオーダーを設定するメソッドです。画面のデザインを ui ファイルではなくソースコードで作成する場合にはこのメソッドを使用してください。この際、上記の例のように 必ず1番目から順番に 1番目→2番目、2番目→3番目、3番目→4番目、… と指定するようにします。また、異なるウィンドウ間ではこの設定はできません。詳細は [qt QWidget setTabOrder] のドキュメントを参照してください。

フォーカス移動の設定

フォームを作成する際に、あるウィジェットはタブキーではフォーカスを移さないようにしたいという場合もあるでしょう。その場合はウィジェットのプロパティ [qt "focusPolicy" l=qwidget m=#focusPolicy-prop] に [qt "Qt::ClickFocus" l=qt m=#FocusPolicy-enum] を設定することで実現可能です。

FocusPolicy を ClickFocus に変更

focusPolicy プロパティに設定可能な項目は以下の通りになります。作成する画面がユーザーにとって使いやすいものになるように、必要な場合には設定を行ってください。

Qt::NoFocus
タブキーでもマウスのクリックでもフォーカスを移さない。
Label などのフォーカスを持たないウィジェットで使われます。
Qt::TabFocus
タブキーでのみフォーカスを移す。
マウスのクリックではフォーカスを移さない設定です。主に Qt 内部での処理のためにあるオプションで、通常この値を設定することはありません。
Qt::ClickFocus
マウスのクリックでのみフォーカスを移す。
タブキーでフォーカスを移したくないウィジェットに設定してください。
Qt::StrongFocus
タブキーでもマウスのクリックでもフォーカスを移す。
フォーカスを持つウィジェットはこちらがデフォルトで設定されています。
Qt::WheelFocus
さらにマウスホイールでもフォーカスを移す。
タブキーとマウスのクリックに加え、マウスのホイールを使用した場合にもフォーカスを移す場合に設定してください。

なお、Mac で「フルキーボードアクセス」が "テキストボックスとリストのみ" になっている場合にタブキーでフォーカスを移動するウィジェットは [qt "Qt::StrongFocus" l=qt m=#FocusPolicy-enum] が設定されている必要があります。

おわりに

今回はタブオーダーについて学びました。前回のアクセスキーの設定と共に、マウスを使わずにウィジェット間を移動するための重要な機能です。アプリケーションを使用するユーザーにとって最適な順番となるように確認、設定を心がけましょう。


Blog Topics:

Comments