「Qtのコントロール - キーボード」の版間の差分

📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

 
(同じ利用者による、間の10版が非表示)
1行目: 1行目:
== 概要 ==
== 概要 ==
 
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>
<br><br>


== キーボード入力 ==
== 単一キーの取得 ==
フォーカスを持つオブジェクトに破棄されたイベントは、<code>keyPressEvent</code>メソッドで受け取れない。<br>
単一キーが押下された場合を取得するには、<code>keyPressEvent</code>メソッドを使用する。<br>
<br>
ただし、フォーカスを持つオブジェクトに破棄されたイベントは、<code>keyPressEvent</code>メソッドで受け取れない。<br>
イベント一括処理で破棄されたイベントは受け取れない。<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++">
  <syntaxhighlight lang="c++">
  // Mainwindow.h
  // Mainwindow.h
22行目: 72行目:
  void MainWindow::keyPressEvent(QKeyEvent *pEvent)
  void MainWindow::keyPressEvent(QKeyEvent *pEvent)
  {
  {
     switch (pEvent->key())
     switch (pEvent->key()) {
    {
       case Qt::Key_Escape:
       case Qt::Key_Escape:
           qDebug() << "Esc keyPress";
           qDebug() << "Esc keyPress";
          pEvent->accept();
           break;
           break;
       case Qt::Key_Return:
       case Qt::Key_Return:
32行目: 82行目:
       case Qt::Key_Enter:
       case Qt::Key_Enter:
           qDebug() << "Enter(keypad) keyPress";
           qDebug() << "Enter(keypad) keyPress";
          pEvent->accept();
           break;
           break;
       case Qt::Key_Home:
       case Qt::Key_Home:
           qDebug() << "Home keyPress";
           qDebug() << "Home keyPress";
          pEvent->accept();
           break;
           break;
       case Qt::Key_Left:
       case Qt::Key_Left:
           qDebug() << "Left keyPress";
           qDebug() << "Left keyPress";
          pEvent->accept();
           break;
           break;
       case Qt::Key_Down:
       case Qt::Key_Down:
           qDebug() << "Down keyPress";
           qDebug() << "Down keyPress";
          pEvent->accept();
           break;
           break;
       case Qt::Key_Space:
       case Qt::Key_Space:
           qDebug() << "Space keyPress";
           qDebug() << "Space keyPress";
          pEvent->accept();
           break;
           break;
       case Qt::Key_F1:
       case Qt::Key_F1:
           qDebug() << "F1 keyPress";
           qDebug() << "F1 keyPress";
          pEvent->accept();
           break;
           break;
       case Qt::Key_0:
       case Qt::Key_0:
           qDebug() << "0(keypad) keyPress";
           qDebug() << "0(keypad) keyPress";
          pEvent->accept();
           break;
           break;
       default:
       default:
           qDebug("keyPress %x", pEvent->key());
           qDebug("keyPress %x", pEvent->key());
          QMainWindow::keyPressEvent(pEvent);  // 基底クラスの呼び出し
           break;
           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);  // 基底クラスの呼び出し
     }
     }
  }
  }
188行目: 294行目:
   
   
  // コンストラクタでイベントフィルタをインストールする
  // コンストラクタでイベントフィルタをインストールする
  MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
  MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
  {
  {
    ui->setupUi(this);
     installEventFilter(this);
     installEventFilter(this);
  }
  }
287行目: 394行目:
  }
  }
  </syntaxhighlight>
  </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>
<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__
__FORCETOC__
[[カテゴリ:Qt]]
[[カテゴリ:Qt]]