「Qtのコントロール - キーボード」の版間の差分
ナビゲーションに移動
検索に移動
(→方法 3) |
(→方法 4) |
||
| 392行目: | 392行目: | ||
} | } | ||
</syntaxhighlight> | </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> | ||
__FORCETOC__ | __FORCETOC__ | ||
[[カテゴリ:Qt]] | [[カテゴリ:Qt]] | ||
2021年3月30日 (火) 13:49時点における版
概要
単一キーの取得
フォーカスを持つオブジェクトに破棄されたイベントは、keyPressEventメソッドで受け取れない。
イベント一括処理で破棄されたイベントは受け取れない。
// Mainwindow.h
// ...略
protected:
void keyPressEvent(QKeyEvent *pEvent);
// Mainwindow.cpp
// 押下したキー名をデバッグ出力する
// その他のキーは、16進数を出力する
void MainWindow::keyPressEvent(QKeyEvent *pEvent)
{
switch (pEvent->key())
{
case Qt::Key_Escape:
qDebug() << "Esc keyPress";
break;
case Qt::Key_Return:
qDebug() << "Return keyPress";
break;
case Qt::Key_Enter:
qDebug() << "Enter(keypad) keyPress";
break;
case Qt::Key_Home:
qDebug() << "Home keyPress";
break;
case Qt::Key_Left:
qDebug() << "Left keyPress";
break;
case Qt::Key_Down:
qDebug() << "Down keyPress";
break;
case Qt::Key_Space:
qDebug() << "Space keyPress";
break;
case Qt::Key_F1:
qDebug() << "F1 keyPress";
break;
case Qt::Key_0:
qDebug() << "0(keypad) keyPress";
break;
default:
qDebug("keyPress %x", pEvent->key());
break;
}
}
複数のキーの取得
方法 1
1つのキーボードイベントで、複数のキーを取得する。
// 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)
// ...略
};
// 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();
}
方法 2
押下したキーをQSetクラスに追加して、キーを離す時にQSetクラスから削除する。
イベントフィルタを使用して、主要なイベントを捕捉する。
// 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)
// ...略
};
// コンストラクタでイベントフィルタをインストールする
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;
}
方法 3
イベントフィルタを使用して、キーボードやマウスのイベントを一括で処理する。
ただし、全てのイベントを処理できるか不明である。
イベント処理の順番は、以下のような流れである。
- フォーカスされているオブジェクトのイベント処理
- イベントフィルタ(
eventFilterメソッド) mousePressEventメソッドやkeyPressEventメソッド等
KeyPress関連のイベント等は、イベントフィルタの前にオブジェクトで消費されるため、
オブジェクトで使用されなかったイベントのみをイベントフィルタで取得することができる。
// MainWindow.h
// イベントフィルタとイベントメソッドを宣言する
protected:
bool eventFilter(QObject *object, QEvent *event);
private:
bool eventKeyPress(QKeyEvent *event);
bool eventKeyRelease(QKeyEvent *event);
// 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;
}
方法 4
一括処理でKeyPressイベントを取得する場合は、QEvent::ShortcutOverrideを使用して、標準ショートカットを上書きする。
ただし、同じキーが2つセット(PressとRelease)で来るので注意が必要である。
// MainWindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
// ...略
// イベントフィルタとメソッドを宣言する
protected:
bool eventFilter(QObject *obj, QEvent *pEvent);
private:
bool MyKeyPress(QKeyEvent *pEvent);
// ...略
}
// 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;
}
複数キーとシグナル
以下の例では、[Ctrl] + [Shift] + [↓]キーを同時押下する時にシグナルを発行している。
シグナルを受信するメソッドは、メッセージボックスを表示してソフトウェアを終了する。
また、シグナルを使用せずにスロットを呼ぶことで同様のことが可能である。
// Mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
// ...略
protected:
bool eventFilter(QObject *obj, QEvent *pEvent);
signals:
void myCloseSIG();
private slots:
void quitProgram();
// ...略
}
// 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;
}
表. 併用キー[enum Qt::KeyboardModifier]
| 定義 | 意味 |
|---|---|
| Qt::NoModifier | なし |
| Qt::ShiftModifier | Shift |
| Qt::ControlModifier | Ctrl |
| Qt::AltModifier | Alt |
| Qt::MetaModifier | Meta |
| Qt::KeypadModifier | Keypad |