Qt QTextEditのTabキー制御:tabChangesFocus徹底解説

2025-05-16

役割

通常、QTextEditのようなテキスト編集ウィジェットでTabキーを押すと、テキスト内にタブ文字(インデント)が挿入されます。しかし、フォームなどで複数の入力欄(QLineEditや他のQTextEditなど)がある場合、Tabキーを使って次の入力欄にフォーカスを移動させたいことがあります。

tabChangesFocusプロパティは、この挙動を切り替えるために使用されます。

  • tabChangesFocusがtrueの場合
    Tabキーを押すと、QTextEditは現在のフォーカスを失い、Tab順で次のウィジェットにフォーカスが移動します。これにより、ユーザーはTabキーを使ってフォーム内の入力欄を順に移動できるようになります。

  • tabChangesFocusがfalse(デフォルト)の場合
    Tabキーを押すと、QTextEdit内にタブ文字が挿入されます。

コードで設定する場合と、Qt DesignerなどのUIファイルで設定する場合の2通りがあります。

コードでの設定例

#include <QTextEdit>
#include <QVBoxLayout>
#include <QPushButton> // 例として、フォーカス移動の対象となる他のウィジェット

// ... (Qtアプリケーションの初期化など)

QTextEdit* textEdit = new QTextEdit();
textEdit->setTabChangesFocus(true); // Tabキーでフォーカスが移動するように設定

QLineEdit* lineEdit = new QLineEdit(); // フォーカス移動の対象となる別のウィジェット

QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(textEdit);
layout->addWidget(lineEdit);

QWidget* centralWidget = new QWidget();
centralWidget->setLayout(layout);
// ... (MainWindowにcentralWidgetを設定など)

Qt Designer(.uiファイル)での設定例

Qt DesignerでQTextEditを配置し、プロパティエディタでtabChangesFocusというプロパティを探します。通常、これはブール値(チェックボックス)として表示されるので、チェックを入れることでtrueに設定できます。



tabChangesFocus(true)に設定してもTabキーでフォーカスが移動しない

考えられる原因

  • Qtのバグ
    ごく稀に、特定のQtバージョンでsetTabChangesFocusが期待通りに動作しないバグが存在する可能性があります。Qtのバグトラッカーなどで類似の報告がないか確認することをおすすめします。
  • 他のイベントハンドリングがTabキーを消費している
    稀に、アプリケーション内でTabキーイベントを横取りするようなカスタムイベントフィルタやイベントハンドラが設定されている場合があります。
  • 次のウィジェットが存在しない、またはフォーカスを受け付けない
    QTextEditの次にフォーカス可能なウィジェットが配置されていない、またはそのウィジェットがsetFocusPolicy(Qt::NoFocus)などでフォーカスを受け付けない設定になっている。
  • Tab順が正しく設定されていない
    tabChangesFocustrueに設定されていても、次のウィジェットへのTab順(tab order)が定義されていない場合、どこにフォーカスを移動させればよいかQtが判断できません。

トラブルシューティング

  • 最小限の再現コードで試す
    問題の切り分けのため、QTextEditと他のいくつかのウィジェットだけを含むシンプルなアプリケーションを作成し、そこでsetTabChangesFocus(true)が機能するかどうかをテストします。
  • デバッグ出力でキーイベントを追跡する
    eventFilterを実装して、QTextEditがTabキーイベントを受け取っているか、そしてそのイベントがQTextEditによって処理されているか(または次のウィジェットに伝播しているか)を確認できます。
  • 次のウィジェットがフォーカス可能か確認する
    • 次のウィジェットがsetEnabled(false)setVisible(false)になっていないか確認します。
    • setFocusPolicy()Qt::TabFocusQt::ClickFocus、またはQt::StrongFocusなどに設定されているか確認します(デフォルトは通常、これらのいずれかです)。
  • Tab順を確認する
    • Qt Designerを使用している場合
      Qt Designerの「Tab順の編集」モード(通常、ツールバーにあるTabキーのアイコン)で、ウィジェット間のTab順が意図通りに設定されているか視覚的に確認します。
    • コードで設定している場合
      QWidget::setTabOrder()関数を使用して、明示的にTab順を設定しているか確認します。設定していない場合、ウィジェットがレイアウトに追加された順序が暗黙的なTab順になります。

tabChangesFocus(false)に設定してもTabキーがタブ文字を挿入しない

考えられる原因

  • Qt Designerでの設定とコードでの設定の競合
    Qt Designerでtrueに設定され、コードでfalseに設定しようとしているが、コードでの設定が適用されるタイミングが遅いなどの問題。
  • 意図せずtrueに設定されている
    コードのどこかで誤ってsetTabChangesFocus(true)が呼び出されている可能性があります。

トラブルシューティング

  • オブジェクトの初期化順序を確認する
    ウィジェットの初期化やプロパティ設定の順序が関係している可能性も考えられます。
  • Qt Designerの設定を確認する
    Qt DesignerでQTextEditを選択し、プロパティエディタでtabChangesFocusがどのように設定されているか再確認します。
  • コード全体でsetTabChangesFocusの呼び出しを検索する
    プロジェクト全体でsetTabChangesFocusがどこで呼び出されているか確認し、意図しない設定がないかチェックします。

QTextEditが意図しないフォーカス挙動を示す

考えられる原因

  • 親ウィジェットのフォーカス管理
    QTextEditが配置されている親ウィジェット(例: QDialogQGroupBox)が、カスタムのフォーカス管理ロジックを持っている場合があります。
  • focusPolicyの設定ミス
    QTextEdit自体のfocusPolicysetFocusPolicy())がQt::NoFocusなどに設定されている場合、Tabキーでフォーカスが移動しようとしても、そもそもQTextEditがフォーカスを受け付けないため、期待通りの動作になりません。

トラブルシューティング

  • 親ウィジェットの挙動を確認する
    親ウィジェットのイベントフィルタやキープレスイベントハンドラで、Tabキーイベントが特別に処理されていないか確認します。
  • QTextEditのfocusPolicyを確認する
    qDebug() << "Focus policy:" << textEdit->focusPolicy();
    
    通常はQt::StrongFocusまたはQt::TabFocusであるべきです。もしQt::NoFocusなら、textEdit->setFocusPolicy(Qt::StrongFocus);などと設定し直します。

考えられる原因

  • OSのアクセシビリティ設定
    OSレベルでのTabキーの挙動やアクセシビリティ設定が、Qtアプリケーションのフォーカス挙動に影響を与えることがあります。
  • Qtのバージョン
    古いQtバージョンや、特定のOSでの動作に違いがある場合があります。
  • 異なるOSや環境でテストする
    可能であれば、異なるオペレーティングシステムや異なるQtバージョンでアプリケーションをテストし、問題が特定の環境に限定されるかどうかを確認します。
  • Qtのドキュメントを確認する
    使用しているQtのバージョンに対応するQTextEditのドキュメントで、tabChangesFocusに関する特記事項がないか確認します。


C++での例

このC++の例では、2つのQTextEditと1つのQLineEditを持つシンプルなウィンドウを作成し、一方のQTextEditではtabChangesFocustrueに設定し、もう一方ではデフォルトのfalseのままにします。

#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QTextEdit>
#include <QLineEdit>
#include <QLabel>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWidget window;
    window.setWindowTitle("QTextEdit::tabChangesFocus Example (C++)");

    QVBoxLayout* layout = new QVBoxLayout(&window);

    // --- QTextEdit 1 (tabChangesFocus = true) ---
    QLabel* label1 = new QLabel("QTextEdit 1 (Tab Changes Focus):");
    QTextEdit* textEdit1 = new QTextEdit();
    textEdit1->setTabChangesFocus(true); // ★ ここでtrueに設定
    textEdit1->setPlainText("これは最初のQTextEditです。\nTabキーを押すと次の入力欄にフォーカスが移動します。");

    layout->addWidget(label1);
    layout->addWidget(textEdit1);

    // --- QTextEdit 2 (tabChangesFocus = false, デフォルト) ---
    QLabel* label2 = new QLabel("QTextEdit 2 (Tab Inserts Tab Character):");
    QTextEdit* textEdit2 = new QTextEdit();
    // textEdit2->setTabChangesFocus(false); // デフォルトなので省略可能
    textEdit2->setPlainText("これは2番目のQTextEditです。\nTabキーを押すとタブ文字が挿入されます。");

    layout->addWidget(label2);
    layout->addWidget(textEdit2);

    // --- QLineEdit (フォーカス移動の対象) ---
    QLabel* label3 = new QLabel("QLineEdit (Focus Target):");
    QLineEdit* lineEdit = new QLineEdit();
    lineEdit->setPlaceholderText("ここに文字を入力してください");

    layout->addWidget(label3);
    layout->addWidget(lineEdit);

    // レイアウトにスペースを追加して見やすくする
    layout->addStretch();

    window.resize(400, 300);
    window.show();

    return app.exec();
}

解説

  1. QTextEdit* textEdit1 = new QTextEdit(); で最初のQTextEditを作成します。
  2. textEdit1->setTabChangesFocus(true); で、このQTextEditでTabキーが押されたときにフォーカスが移動するように設定します。
  3. QTextEdit* textEdit2 = new QTextEdit(); で2番目のQTextEditを作成します。ここではsetTabChangesFocusを呼び出していません。QTextEdittabChangesFocusプロパティのデフォルト値はfalseなので、Tabキーを押すとタブ文字が挿入されます。
  4. QLineEdit* lineEdit = new QLineEdit(); は、textEdit1からTabキーでフォーカスが移動する先のウィジェットとして機能します。

このコードを実行すると、textEdit1にフォーカスがある状態でTabキーを押すとlineEditにフォーカスが移動します。一方、textEdit2にフォーカスがある状態でTabキーを押すと、textEdit2内にタブ文字が挿入されます。

Python (PySide6またはPyQt6) でも同様のことができます。

import sys
from PySide6.QtWidgets import (QApplication, QWidget, QVBoxLayout,
                               QTextEdit, QLineEdit, QLabel)
# または PyQt6 を使用する場合:
# from PyQt6.QtWidgets import (QApplication, QWidget, QVBoxLayout,
#                                QTextEdit, QLineEdit, QLabel)

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QTextEdit::tabChangesFocus Example (Python)")
        self.init_ui()

    def init_ui(self):
        layout = QVBoxLayout()

        # --- QTextEdit 1 (tabChangesFocus = True) ---
        label1 = QLabel("QTextEdit 1 (Tab Changes Focus):")
        self.text_edit1 = QTextEdit()
        self.text_edit1.setTabChangesFocus(True) # ★ ここでTrueに設定
        self.text_edit1.setPlainText("これは最初のQTextEditです。\nTabキーを押すと次の入力欄にフォーカスが移動します。")

        layout.addWidget(label1)
        layout.addWidget(self.text_edit1)

        # --- QTextEdit 2 (tabChangesFocus = False, デフォルト) ---
        label2 = QLabel("QTextEdit 2 (Tab Inserts Tab Character):")
        self.text_edit2 = QTextEdit()
        # self.text_edit2.setTabChangesFocus(False) # デフォルトなので省略可能
        self.text_edit2.setPlainText("これは2番目のQTextEditです。\nTabキーを押すとタブ文字が挿入されます。")

        layout.addWidget(label2)
        layout.addWidget(self.text_edit2)

        # --- QLineEdit (フォーカス移動の対象) ---
        label3 = QLabel("QLineEdit (Focus Target):")
        self.line_edit = QLineEdit()
        self.line_edit.setPlaceholderText("ここに文字を入力してください")

        layout.addWidget(label3)
        layout.addWidget(self.line_edit)

        # レイアウトにスペースを追加して見やすくする
        layout.addStretch()

        self.setLayout(layout)
        self.resize(400, 300)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

解説

Python版もC++版とほぼ同じロジックです。

  1. self.text_edit1 = QTextEdit() で最初のQTextEditを作成します。
  2. self.text_edit1.setTabChangesFocus(True) で、このQTextEditでTabキーが押されたときにフォーカスが移動するように設定します。Pythonではブール値はTrueまたはFalseと大文字で記述します。
  3. self.text_edit2 = QTextEdit() はデフォルトの挙動(タブ文字挿入)を維持します。
  4. self.line_edit = QLineEdit() はフォーカス移動のターゲットです。


QTextEditをサブクラス化し、keyPressEvent()をオーバーライドする

この方法は、QTextEditがTabキーイベントを受け取った際に、そのイベントをどのように処理するかを完全に制御したい場合に最も一般的で強力な方法です。

考え方

QTextEditを継承したカスタムクラスを作成し、keyPressEvent(QKeyEvent *event)メソッドを再実装します。このメソッド内で、押されたキーがTabキーであるかどうかをチェックし、それに応じてカスタムロジックを実行します。

  • Tabキー以外の場合
    • 通常のテキスト編集動作を維持するために、親クラスのQTextEdit::keyPressEvent(event)を呼び出します。
  • Tabキーの場合
    • フォーカスを次のウィジェットに移動させたい場合は、QWidget::focusNextPrevChild(true)を呼び出します(trueは次のウィジェット、falseは前のウィジェットを意味します)。
    • イベントを処理したことを示すためにevent->accept()を呼び出し、親クラスのkeyPressEventにはイベントを渡しません。

C++での例

#include <QTextEdit>
#include <QKeyEvent>
#include <QApplication>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QLabel>

// カスタムQTextEditクラス
class MyTextEdit : public QTextEdit
{
    Q_OBJECT // シグナル/スロットを使用する場合に必要
public:
    explicit MyTextEdit(QWidget *parent = nullptr) : QTextEdit(parent) {}

protected:
    void keyPressEvent(QKeyEvent *event) override
    {
        // Tabキーが押された場合
        if (event->key() == Qt::Key_Tab) {
            // シフトキーが押されていれば逆方向に移動 (Shift+Tab)
            if (event->modifiers() & Qt::ShiftModifier) {
                focusNextPrevChild(false); // 前のウィジェットへフォーカス移動
            } else {
                focusNextPrevChild(true);  // 次のウィジェットへフォーカス移動
            }
            event->accept(); // イベントを処理済みとしてマークし、親クラスへ伝播させない
        }
        // Enterキーが押された場合(例として、Enterキーでもフォーカス移動)
        else if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
            focusNextPrevChild(true);
            event->accept();
        }
        // その他のキーの場合
        else {
            QTextEdit::keyPressEvent(event); // 親クラスのデフォルト処理を呼び出す
        }
    }
};

#include "main.moc" // mocファイルをインクルード (Q_OBJECTを使用する場合)

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWidget window;
    window.setWindowTitle("Custom QTextEdit KeyPressEvent Example (C++)");

    QVBoxLayout* layout = new QVBoxLayout(&window);

    QLabel* label1 = new QLabel("MyTextEdit (Tab/Enter changes focus):");
    MyTextEdit* textEdit1 = new MyTextEdit(); // カスタムクラスを使用
    textEdit1->setPlainText("このQTextEditでは、TabまたはEnterキーでフォーカスが移動します。");

    layout->addWidget(label1);
    layout->addWidget(textEdit1);

    QLabel* label2 = new QLabel("QTextEdit (Default behavior):");
    QTextEdit* textEdit2 = new QTextEdit();
    textEdit2->setPlainText("このQTextEditでは、Tabキーでタブ文字が挿入されます。");

    layout->addWidget(label2);
    layout->addWidget(textEdit2);

    QLabel* label3 = new QLabel("QLineEdit (Focus Target):");
    QLineEdit* lineEdit = new QLineEdit();
    lineEdit->setPlaceholderText("ここに文字を入力してください");

    layout->addWidget(label3);
    layout->addWidget(lineEdit);

    window.resize(400, 300);
    window.show();

    return app.exec();
}

Python (PySide6 / PyQt6) での例

import sys
from PySide6.QtWidgets import (QApplication, QWidget, QVBoxLayout,
                               QTextEdit, QLineEdit, QLabel)
from PySide6.QtCore import Qt
from PySide6.QtGui import QKeyEvent

class MyTextEdit(QTextEdit):
    def __init__(self, parent=None):
        super().__init__(parent)

    def keyPressEvent(self, event: QKeyEvent):
        if event.key() == Qt.Key_Tab:
            if event.modifiers() & Qt.ShiftModifier:
                self.focusNextPrevChild(False) # Shift+Tabで前のウィジェットへ
            else:
                self.focusNextPrevChild(True)  # Tabで次のウィジェットへ
            event.accept() # イベントを処理済みとしてマーク
        elif event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter:
            self.focusNextPrevChild(True)
            event.accept()
        else:
            super().keyPressEvent(event) # 親クラスのデフォルト処理を呼び出す

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Custom QTextEdit KeyPressEvent Example (Python)")
        self.init_ui()

    def init_ui(self):
        layout = QVBoxLayout()

        label1 = QLabel("MyTextEdit (Tab/Enter changes focus):")
        self.text_edit1 = MyTextEdit() # カスタムクラスを使用
        self.text_edit1.setPlainText("このQTextEditでは、TabまたはEnterキーでフォーカスが移動します。")
        layout.addWidget(label1)
        layout.addWidget(self.text_edit1)

        label2 = QLabel("QTextEdit (Default behavior):")
        self.text_edit2 = QTextEdit()
        self.text_edit2.setPlainText("このQTextEditでは、Tabキーでタブ文字が挿入されます。")
        layout.addWidget(label2)
        layout.addWidget(self.text_edit2)

        label3 = QLabel("QLineEdit (Focus Target):")
        self.line_edit = QLineEdit()
        self.line_edit.setPlaceholderText("ここに文字を入力してください")
        layout.addWidget(label3)
        layout.addWidget(self.line_edit)

        self.setLayout(layout)
        self.resize(400, 300)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

イベントフィルターを使用する

ウィジェットをサブクラス化せずに、特定のウィジェットのイベントを監視・変更したい場合に、イベントフィルターが便利です。

考え方

QObject::installEventFilter()を使って、監視したいウィジェットにイベントフィルターをインストールします。イベントフィルタークラス(または親ウィジェット)はeventFilter(QObject *watched, QEvent *event)メソッドを実装し、ここで特定のイベント(今回の場合はQEvent::KeyPressとTabキー)をインターセプトして処理します。

  • イベントを処理しない場合はfalseを返し、元のウィジェットや他のフィルターにイベントが伝播するようにします。
  • イベントを処理した場合はtrueを返し、それ以上イベントを伝播させないようにします。

C++での例

#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QTextEdit>
#include <QLineEdit>
#include <QLabel>
#include <QKeyEvent>

// イベントフィルタークラス
class TabFocusEventFilter : public QObject
{
public:
    explicit TabFocusEventFilter(QObject *parent = nullptr) : QObject(parent) {}

protected:
    bool eventFilter(QObject *watched, QEvent *event) override
    {
        if (event->type() == QEvent::KeyPress) {
            QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
            if (keyEvent->key() == Qt::Key_Tab) {
                // Tabキーが押されたウィジェットがQTextEditの場合のみ適用
                if (qobject_cast<QTextEdit*>(watched)) {
                    if (keyEvent->modifiers() & Qt::ShiftModifier) {
                        qobject_cast<QWidget*>(watched)->focusNextPrevChild(false);
                    } else {
                        qobject_cast<QWidget*>(watched)->focusNextPrevChild(true);
                    }
                    keyEvent->accept(); // イベントを処理済みとしてマーク
                    return true; // イベントの伝播を停止
                }
            }
        }
        return QObject::eventFilter(watched, event); // それ以外のイベントは通常通り処理
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWidget window;
    window.setWindowTitle("Event Filter Example (C++)");

    QVBoxLayout* layout = new QVBoxLayout(&window);

    QLabel* label1 = new QLabel("QTextEdit (with Event Filter - Tab changes focus):");
    QTextEdit* textEdit1 = new QTextEdit();
    textEdit1->setPlainText("このQTextEditでは、イベントフィルターによってTabキーでフォーカスが移動します。");

    // イベントフィルターをインストール
    TabFocusEventFilter* filter = new TabFocusEventFilter(&window); // 親をwindowにする
    textEdit1->installEventFilter(filter);

    layout->addWidget(label1);
    layout->addWidget(textEdit1);

    QLabel* label2 = new QLabel("QTextEdit (Default behavior):");
    QTextEdit* textEdit2 = new QTextEdit();
    textEdit2->setPlainText("このQTextEditでは、Tabキーでタブ文字が挿入されます。");

    layout->addWidget(label2);
    layout->addWidget(textEdit2);

    QLabel* label3 = new QLabel("QLineEdit (Focus Target):");
    QLineEdit* lineEdit = new QLineEdit();
    lineEdit->setPlaceholderText("ここに文字を入力してください");

    layout->addWidget(label3);
    layout->addWidget(lineEdit);

    window.resize(400, 300);
    window.show();

    return app.exec();
}
import sys
from PySide6.QtWidgets import (QApplication, QWidget, QVBoxLayout,
                               QTextEdit, QLineEdit, QLabel)
from PySide6.QtCore import Qt, QEvent, QObject
from PySide6.QtGui import QKeyEvent

class TabFocusEventFilter(QObject):
    def eventFilter(self, watched: QObject, event: QEvent) -> bool:
        if event.type() == QEvent.Type.KeyPress:
            key_event = event # QKeyEventとして扱う
            if key_event.key() == Qt.Key.Key_Tab:
                # 監視対象がQTextEditであることを確認
                if isinstance(watched, QTextEdit):
                    if key_event.modifiers() & Qt.Modifier.ShiftModifier:
                        watched.focusNextPrevChild(False)
                    else:
                        watched.focusNextPrevChild(True)
                    key_event.accept() # イベントを処理済みとしてマーク
                    return True # イベントの伝播を停止

        return super().eventFilter(watched, event) # それ以外のイベントは通常通り処理

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Event Filter Example (Python)")
        self.init_ui()

    def init_ui(self):
        layout = QVBoxLayout()

        label1 = QLabel("QTextEdit (with Event Filter - Tab changes focus):")
        self.text_edit1 = QTextEdit()
        self.text_edit1.setPlainText("このQTextEditでは、イベントフィルターによってTabキーでフォーカスが移動します。")

        # イベントフィルターをインストール
        self.filter = TabFocusEventFilter(self) # 親をMainWindowにする
        self.text_edit1.installEventFilter(self.filter)

        layout.addWidget(label1)
        layout.addWidget(self.text_edit1)

        label2 = QLabel("QTextEdit (Default behavior):")
        self.text_edit2 = QTextEdit()
        self.text_edit2.setPlainText("このQTextEditでは、Tabキーでタブ文字が挿入されます。")
        layout.addWidget(label2)
        layout.addWidget(self.text_edit2)

        label3 = QLabel("QLineEdit (Focus Target):")
        self.line_edit = QLineEdit()
        self.line_edit.setPlaceholderText("ここに文字を入力してください")
        layout.addWidget(label3)
        layout.addWidget(self.line_edit)

        self.setLayout(layout)
        self.resize(400, 300)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())
  • イベントフィルター

    • 既存のウィジェットをサブクラス化せずに、そのイベント処理を変更したい場合に便利です。
    • 複数の異なるウィジェットに対して同じイベント処理ロジックを適用したい場合(例えば、アプリケーション全体でTabキーの挙動を統一したいが、すべてのウィジェットをサブクラス化するのは面倒な場合)に有効です。
    • オブジェクト指向設計の観点から、関心事の分離(Separation of Concerns)を促進できます。
  • keyPressEvent()のオーバーライド

    • Tabキーだけでなく、Enterキーや他のキーの挙動も細かく制御したい場合に適しています。
    • 例えば、Tabキーでフォーカスを移動させつつ、Shift+Tabで逆方向に移動させたい場合(上記例のように)など、より複雑なロジックを実装できます。
    • カスタムウィジェットを作成する際に自然なアプローチです。
  • setTabChangesFocus()

    • 最もシンプルで、Qtの推奨するアプローチです。
    • QTextEditがTabキーでフォーカスを移動するか、タブ文字を挿入するかを簡単に切り替えたい場合に最適です。
    • 特別なカスタマイズが不要であれば、まずこのプロパティを検討すべきです。