MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
Qtのコントロール - キーボードのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
Qtのコントロール - キーボード
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == Qt Widgetでのキーボードの入力制御は、ユーザインターフェースの重要な要素である。<br> 基本的には、<code>QKeyEvent</code>クラスを使用して、キーボードイベントを処理する。<br> <br> 主な方法として、<code>keyPressEvent</code>メソッドおよび<code>keyReleaseEvent</code>メソッドをオーバーライドすることが挙げられる。<br> これらのメソッドは、キーの押下あるいはリリースした時に呼び出される。<br> <br> 例えば、特定のキーが押下された時に任意の動作を実行する場合、以下に示すように記述する。<br> <br> <syntaxhighlight lang="c++"> void MyWidget::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Return) { // [Enter]キーが押下された場合 } else { QWidget::keyPressEvent(event); } } </syntaxhighlight> <br> また、ショートカットキーを設定する場合は、<code>QShortcut</code>クラスを使用する。<br> これにより、特定のキーの組み合わせに対してアクションを割り当てることができる。<br> <br> フォーカスの制御も重要な要素である。<br> [Tab]キーを使用してウィジェット間を移動できるようにするには、<code>setFocusPolicy</code>メソッドを使用してフォーカスポリシーを設定する。<br> <br> キーボードイベントをフィルタリングする場合は、<code>eventFilter</code>メソッドを使用することもできる。<br> これにより、特定のウィジェットに対するキーボードイベントをインターセプトして、カスタム処理を行うことが可能である。<br> <br> アクセシビリティの観点からは、キーボードナビゲーションを適切に実装することが重要である。<br> これには、ショートカットキーの提供、論理的なタブ順序の設定、フォーカスインジケータの実装等が含まれる。<br> <br> 使用例としては、カスタムキーシーケンスの実装やテキスト入力のカスタマイズ等がある。<br> これらは、より複雑なユーザインターフェースや特殊な入力要件がある場合に役立つ。<br> <br> キーボードの入力制御を実装する場合は、異なるプラットフォームや言語での動作の違いに注意する必要がある。<br> Qtでは、多くの場合これらの違いを抽象化するが、特定のケースでは追加の対応が必要になることがある。<br> <br><br> == 単一キーの取得 == 単一キーが押下された場合を取得するには、<code>keyPressEvent</code>メソッドを使用する。<br> <br> ただし、フォーカスを持つオブジェクトに破棄されたイベントは、<code>keyPressEvent</code>メソッドで受け取れない。<br> イベント一括処理で破棄されたイベントは受け取れない。<br> <br> <u>※注意</u><br> * 基底クラスの呼び出し *: 未処理のキーイベントを適切に処理するため、デフォルトケースで基底クラスの<code>keyPressEvent</code>を呼び出すことが推奨される。 * キーの繰り返し *: 長押しによるキーの繰り返しを区別する場合は、<code>QKeyEvent</code>クラスの<code>isAutoRepeat</code>メソッドを使用する。 * イベントの受理 *: 特定のキーイベントを完全に処理したことを示すため、<code>QKeyEvent</code>クラスの<code>accept</code>メソッドを呼び出す。 *: <br> *: イベントを完全に処理した後、それ以上の伝播を望まない場合は、<code>QKeyEvent</code>クラスの<code>accept</code>メソッドを呼び出す。 *: イベントを処理した後、他のウィジェットやハンドラにも処理の機会を与える場合は、<code>QKeyEvent</code>クラスの<code>ignore</code>メソッドを呼び出す、あるいは、何もしない。 <br> <syntaxhighlight lang="c++"> // Mainwindow.h // ...略 protected: void keyPressEvent(QKeyEvent *pEvent); </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // Mainwindow.cpp // 押下したキー名をデバッグ出力する // その他のキーは、16進数を出力する void MainWindow::keyPressEvent(QKeyEvent *pEvent) { switch (pEvent->key()) { case Qt::Key_Escape: qDebug() << "Esc keyPress"; pEvent->accept(); break; case Qt::Key_Return: qDebug() << "Return keyPress"; break; case Qt::Key_Enter: qDebug() << "Enter(keypad) keyPress"; pEvent->accept(); break; case Qt::Key_Home: qDebug() << "Home keyPress"; pEvent->accept(); break; case Qt::Key_Left: qDebug() << "Left keyPress"; pEvent->accept(); break; case Qt::Key_Down: qDebug() << "Down keyPress"; pEvent->accept(); break; case Qt::Key_Space: qDebug() << "Space keyPress"; pEvent->accept(); break; case Qt::Key_F1: qDebug() << "F1 keyPress"; pEvent->accept(); break; case Qt::Key_0: qDebug() << "0(keypad) keyPress"; pEvent->accept(); break; default: qDebug("keyPress %x", pEvent->key()); QMainWindow::keyPressEvent(pEvent); // 基底クラスの呼び出し break; } // 自動繰り返しを区別する場合 if (pEvent->isAutoRepeat()) { qDebug() << "Key is auto-repeating"; } } </syntaxhighlight> <br><br> == モディファイアキーとの組み合わせ == [Ctrl]キーあるいは[Shift]キー等のモディファイアキーと組み合わせる場合は、<code>QKeyEvent</code>クラスの<code>modifiers</code>メソッドを使用する。<br> <br> <u>※注意</u><br> <u>モディファイアキーと組み合わせた特定のアクションを実行する場合、そのアクションが完全にイベントを消費するならば、<code>accept</code>メソッドを実行する。</u><br> <u>モディファイアキーの状態を記録または確認するだけの場合、<code>accept</code>メソッドは実行せずに、そのイベントを他のハンドラへ渡すほうがよい。</u><br> <br> <syntaxhighlight lang="c++"> // Mainwindow.h // ...略 protected: void keyPressEvent(QKeyEvent *pEvent); </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // Mainwindow.cpp // 押下したキー名をデバッグ出力する // その他のキーは、16進数を出力する void MainWindow::keyPressEvent(QKeyEvent *pEvent) { // モディファイアキーの制御 if (pEvent->modifiers() & Qt::ControlModifier) { if (pEvent->key() == Qt::Key_C) { // 特定のキーイベントのみを消費する場合 qDebug() << "[Ctrl] + [C] pressed"; pEvent->accept(); } else { // ロギングのみを行う場合 qDebug() << "Ctrl is pressed with" << pEvent->key(); } } else { // それ以外の場合は、基底クラスを呼び出すことにより、他のウィジェットやハンドラがイベントを処理する機会を与えることが可能 QMainWindow::keyPressEvent(pEvent); // 基底クラスの呼び出し } } </syntaxhighlight> <br><br> == 複数のキーの取得 == ==== 方法 1 ==== 1つのキーボードイベントで、複数のキーを取得する。<br> <syntaxhighlight lang="c++"> // MainWindows.h class MainWindow : public QMainWindow { Q_OBJECT // ...略 private: Ui::MainWindow *ui; bool m_bFirstRelease; QSet<Qt::Key> m_keysPressed; protected: keyPressEvent(QKeyEvent *pEvent) keyReleaseEvent(QKeyEvent *pEvent) // ...略 }; </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // MainWindow.cpp void MainWindow::keyPressEvent(QKeyEvent *pEvent) { m_bFirstRelease = true; m_keysPressed += pEvent->key(); } void MainWindow::keyReleaseEvent(QKeyEvent *pEvent) { if(m_bFirstRelease) { processMultiKeys(keysPressed); } m_bFirstRelease = false; m_keysPressed -= pEvent->key(); } </syntaxhighlight> <br> ==== 方法 2 ==== 押下したキーをQSetクラスに追加して、キーを離す時にQSetクラスから削除する。<br> イベントフィルタを使用して、主要なイベントを捕捉する。<br> <syntaxhighlight lang="c++"> // MainWindow.h class MainWindow : public QMainWindow { Q_OBJECT // ...略 private: Ui::MainWindow *ui; bool m_bFirstRelease; QSet<int> m_keysPressed; protected: bool eventFilter(QObject *obj, QEvent *pEvent); keyPressEvent(QKeyEvent *pEvent) keyReleaseEvent(QKeyEvent *pEvent) // ...略 }; </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // コンストラクタでイベントフィルタをインストールする MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { installEventFilter(this); } bool MainWindow::eventFilter(QObject *obj, QEvent *pEvent) { if(pEvent->type() == QEvent::KeyPress) { m_keysPressed += ((QKeyEvent*)pEvent)->key(); if(m_keysPressed.contains(Qt::Key_D) && m_keysPressed.contains(Qt::Key_W)) { // [D]キーと[W]キーを同時に押下する場合 // ...処理を記述 } } else if(pEvent->type() == QEvent::KeyRelease) { m_keysPressed -= ((QKeyEvent*)pEvent)->key(); } return false; } </syntaxhighlight> <br> ==== 方法 3 ==== イベントフィルタを使用して、キーボードやマウスのイベントを一括で処理する。<br> ただし、全てのイベントを処理できるか不明である。<br> <br> イベント処理の順番は、以下のような流れである。<br> # フォーカスされているオブジェクトのイベント処理 # イベントフィルタ(<code>eventFilter</code>メソッド) # <code>mousePressEvent</code>メソッドや<code>keyPressEvent</code>メソッド等 <br> KeyPress関連のイベント等は、イベントフィルタの前にオブジェクトで消費されるため、<br> オブジェクトで使用されなかったイベントのみをイベントフィルタで取得することができる。<br> <syntaxhighlight lang="c++"> // MainWindow.h // イベントフィルタとイベントメソッドを宣言する protected: bool eventFilter(QObject *object, QEvent *event); private: bool eventKeyPress(QKeyEvent *event); bool eventKeyRelease(QKeyEvent *event); </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // MainWindow.cpp // コンストラクタでイベントフィルタをインストールする MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); installEventFilter(this); } // イベントごとに必要な処理を行う // trueを返すとイベントは破棄される // installEventFilterメソッドのオブジェクト(QObject)が第1引数として渡されるが、 // ここでは使用しないため、名前を指定しない bool MainWindow::eventFilter(QObject *, QEvent *event) { bool bRtn = false; if(event->type() == QEvent::KeyPress) { bRtn = eventKeyPress(static_cast<QKeyEvent *>(event)); } else if(event->type() == QEvent::KeyRelease) { bRtn = eventKeyRelease(static_cast<QKeyEvent *>(event)); } return bRtn; } // キー押下時の処理 // 特定のキーを判定してデバッグ出力する // その他のキーはfalseを返してイベントを残す // キーを押下している間のリピートキーは破棄する // イベントが取得できるかどうかは、フォーカス次第となる bool MainWindow::eventKeyPress(QKeyEvent *event) { if(event->isAutoRepeat()) { return true; } switch(event->key()) { case Qt::Key_Escape: qDebug() << "Esc press"; break; case Qt::Key_Return: qDebug() << "Return press"; break; case Qt::Key_Enter: qDebug() << "Enter(keypad) press"; break; case Qt::Key_Home: qDebug() << "Home press"; break; case Qt::Key_Left: qDebug() << "Left press"; break; case Qt::Key_Down: qDebug() << "Down press"; break; case Qt::Key_Space: qDebug() << "Space press"; break; case Qt::Key_F1: qDebug() << "F1 press"; break; case Qt::Key_0: qDebug() << "0(keypad) press"; break; default: qDebug("press %x", event->key()); return false; } return true; } // キーを離した時の処理 // KeyReleaseイベントではオブジェクトをあまり消費しないため、イベントを取得できる可能性が高い bool MainWindow::eventKeyRelease(QKeyEvent *event) { if(event->isAutoRepeat()) { return true; } switch(event->key()) { case Qt::Key_Tab: qDebug() << "Tab release"; break; case Qt::Key_Backtab: qDebug() << "Backtab release"; break; default: qDebug("release %x", event->key()); return false; } return true; } </syntaxhighlight> <br> ==== 方法 4 ==== 一括処理でKeyPressイベントを取得する場合は、<code>QEvent::ShortcutOverride</code>を使用して、標準ショートカットを上書きする。<br> ただし、同じキーが2つセット(PressとRelease)で来るので注意が必要である。<br> <syntaxhighlight lang="c++"> // MainWindow.h class MainWindow : public QMainWindow { Q_OBJECT // ...略 // イベントフィルタとメソッドを宣言する protected: bool eventFilter(QObject *obj, QEvent *pEvent); private: bool MyKeyPress(QKeyEvent *pEvent); // ...略 } </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // MainWindow.cpp // コンストラクタでイベントフィルタをインストールする MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); installEventFilter(this); } // ShortcutOverrideで標準ショートカットを上書きしてKeyPressを取得する bool MainWindow::eventFilter(QObject *obj, QEvent *pEvent) { bool bRtn = false; if(pEvent->type() == QEvent::ShortcutOverride) { bRtn = MyKeyPress(static_cast<QKeyEvent *>(pEvent)); } return bRtn; } // キー押下時の処理 // スイッチを使用して1つ破棄する bool MainWindow::MyKeyPress(QKeyEvent *pEvent) { static int sw = -1; if(pEvent->isAutoRepeat()) { return true; } if(pEvent->key() == sw) { sw = -1; return true; } sw = pEvent->key(); switch(pEvent->key()) { case Qt::Key_Escape: qDebug() << "Esc ScutOver"; break; case Qt::Key_Return: qDebug() << "Return ScutOver"; break; case Qt::Key_Enter: qDebug() << "Enter(keypad) ScutOver"; break; case Qt::Key_Home: qDebug() << "Home ScutOver"; break; case Qt::Key_Left: qDebug() << "Left ScutOver"; break; case Qt::Key_Down: qDebug() << "Down ScutOver"; break; case Qt::Key_Space: qDebug() << "Space ScutOver"; break; case Qt::Key_F1: qDebug() << "F1 ScutOver"; break; case Qt::Key_0: qDebug() << "0(keypad) ScutOver"; break; default: qDebug("ScutOver %x", pEvent->key()); return false; } return true; } </syntaxhighlight> <br><br> == 複数キーとシグナル == 以下の例では、[Ctrl] + [Shift] + [↓]キーを同時押下する時にシグナルを発行している。<br> シグナルを受信するメソッドは、メッセージボックスを表示してソフトウェアを終了する。<br> <br> また、シグナルを使用せずにスロットを呼ぶことで同様のことが可能である。<br> <syntaxhighlight lang="c++"> // Mainwindow.h class MainWindow : public QMainWindow { Q_OBJECT // ...略 protected: bool eventFilter(QObject *obj, QEvent *pEvent); signals: void myCloseSIG(); private slots: void quitProgram(); // ...略 } </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // MainWindow.cpp // コンストラクタでシグナルを終了処理関数に接続して、イベントフィルタをインストールする MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); connect(this, SIGNAL(myCloseSIG()), this, SLOT(quitProgram())); installEventFilter(this); } // イベント処理 // [↓]キーを押下する場合、[Shift]キーと[Ctrl]キーが押下されていることを確認してシグナルを発行する bool MainWindow::eventFilter(QObject *obj, QEvent *pEvent) { if(pEvent->type() == QEvent::ShortcutOverride) { QKeyEvent *eKey = static_cast<QKeyEvent *>(pEvent); if(eKey->key() == Qt::Key_Down) { if((eKey->modifiers() & (Qt::ShiftModifier)) && (eKey->modifiers() & (Qt::ControlModifier))) { emit myCloseSIG(); return true; } } } return false; } </syntaxhighlight> <br> <center> 表. 併用キー[enum Qt::KeyboardModifier]<br> {| class="wikitable" style="background-color:#fefefe;" |- ! style="background-color:#00ffff;" | 定義 ! style="background-color:#00ffff;" | 意味 |- | Qt::NoModifier || なし |- | Qt::ShiftModifier || Shift |- | Qt::ControlModifier || Ctrl |- | Qt::AltModifier || Alt |- | Qt::MetaModifier || Meta |- | Qt::KeypadModifier || Keypad |} </center> <br><br> {{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux |image=/resources/assets/MochiuLogo_Single_Blue.png }} __FORCETOC__ [[カテゴリ:Qt]]
Qtのコントロール - キーボード
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse