使用QKeyEvent
类用来描述一个键盘事件。
当键盘按键被按下或者释放时候,键盘事件便会被发送给拥有键盘输入焦点的部件。QKeyEvent的key函数
可以获取具体的按键,对于Qt中给定的所有按键,可以在帮助中通过Qt::Key
关键字查看。需要特别说明的是,回车键在这里是Qt::Key_Return;
键盘上的一些修饰键,比如Ctrl和 Shift等,这里需要使用QKeyEvent的modifiers()函数来获取,可以在帮助中使用Qt: : Keyboard-Modifier
关键字来查看所有的修饰键。下面通过例子来看一下它们具体的应用。
新建Qt widget应用,项目名称为mykeyevent,基类选择QWidget,项目名称mykeyevent, 完成后在widget.h文件中添加函数声明:
protected:
void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
在到widget.cpp文件中实现函数
添加头文件#include< QKeyEvent>
void Widget::keyPressEvent(QKeyEvent *event) // 键盘按下事件
{
if(event->modifiers() == Qt::ControlModifier){ // 是否按下Ctrl键
if(event->key() == Qt::Key_M) // 是否按下M键
setWindowState(Qt::WindowMaximized); // 窗口最大化
}
else QWidget::keyPressEvent(event);
}
void Widget::keyReleaseEvent(QKeyEvent *event) // 按键释放事件
{
// 其他操作
}
这里使用了Ctrl+M键来使窗口最大化,在键盘按下事件处理函数中,先检测Ctrl键是否按下,如果是,那么再检测M键是否按下。可以运行程序测试一下效果。
可不可以使用二个不用的普通按键来实现一定的操作
在设计模式中向界面上拖放一个 Horizontal Line部件,在属性栏中将它的X、Y坐标分别设置为50、100;
再拖入一个Vertical Line部件,将其X、Y坐标分别设置为100、20;然后再拖入一个PushButton,设置其X、Y坐标为120、120,并更改其显示内容为“请按方向键”,最终效果如图所示。
下面打开widget.cpp文件,先添头文件#include< QDebug>,然后再构造函数添加一行代码:
setFocus();
将二个事件函数更改为:
void Widget::keyPressEvent(QKeyEvent *event) // 键盘按下事件
{
if(event->key() == Qt::Key_Up){ // 如果是向上方向键
qDebug() << "press:"<<event->isAutoRepeat(); // 是否自动重复
}
}
void Widget::keyReleaseEvent(QKeyEvent *event) // 按键释放事件
{
if(event->key() == Qt::Key_Up){
qDebug() << "release:"<< event->isAutoRepeat();
qDebug() << "up";
}
}
这里在键盘按下,和释放函数中分别输出了向上方向键是否自动重复的信息。
运行效果:
按一下松开,并不会重复
但是一直按着会自动重复。
如果要实现二个普通按键同时按下,就要避免按键的自动重复。
下面来解决自动重复这个问题:
按下向上方向键按钮上移,按左右左右移动,如果按下左方向键的同时按下向上方向键向左上方移动。
首先在widget.h文件中定义private变量;
bool keyUp; // 向上方向键按下的标志
bool keyLeft; // 向左方向键按下的标志
bool move; // 是否完成了一次移动
然后再widget.cpp中构造函数对变量初始化
keyUp = false; // 初始化变量
keyLeft = false;
move = false;
下面将二个事件处理函数的内容更改如下:
void Widget::keyPressEvent(QKeyEvent *event) // 键盘按下事件
{
// if(event->key() == Qt::Key_Up){ // 如果是向上方向键
// qDebug() << "press:"<<event->isAutoRepeat(); // 是否自动重复
// }
if (event->key() == Qt::Key_Up) {
if(event->isAutoRepeat()) return; // 按键重复时不做处理
keyUp = true; // 标记向上方向键已经按下
}
else if (event->key() == Qt::Key_Left) {
if (event->isAutoRepeat()) return;
keyLeft = true;
}
}
void Widget::keyReleaseEvent(QKeyEvent *event) // 按键释放事件
{
// if(event->key() == Qt::Key_Up){
// qDebug() << "release:"<< event->isAutoRepeat();
// qDebug() << "up";
// }
if (event->key() == Qt::Key_Up) {
if (event->isAutoRepeat()) return;
keyUp = false; // 释放按键后将标志设置为false
if (move) { // 如果已经完成了移动
move = false; // 设置标志为false
return; // 直接返回
}
if (keyLeft) { // 如果向左方向键已经按下且没有释放
ui->pushButton->move(30, 80); // 斜移
move = true; // 标记已经移动
} else { // 否则直接上移
ui->pushButton->move(120, 80);
}
}
else if (event->key() == Qt::Key_Left) {
if (event->isAutoRepeat()) return;
keyLeft = false;
if (move) {
move = false;
return;
}
if (keyUp) {
ui->pushButton->move(30, 80);
move = true;
} else {
ui->pushButton->move(30, 120);
}
}
else if (event->key() == Qt::Key_Down) {
ui->pushButton->move(120, 120); // 使用向下方向键来还原按钮的位置
}
}
这里先在键盘按下事件处理函数中对向上方向键和向左方向键是否按下做了标记,并且当自动重复时不做任何处理。然后在按键释放事件处理函数中分别对这二个按键的释放做了处理。
流程是这样的:
当按下左方向键时候
if (event->key() == Qt::Key_Up) {
if(event->isAutoRepeat()) return; // 按键重复时不做处理
keyUp = true; // 标记向上方向键已经按下
}
else if (event->key() == Qt::Key_Left) {
if (event->isAutoRepeat()) return;
keyLeft = true;
标记KeyLeft为真
此时如果又按下向上方向键,那么keyUp也标记为真。
然后放开向上方向键,在按键释放函数中会标记keyUp为假,因为此时keyLeft为真,所以进行斜移,并且将已经移动标志move标记为真。
if (event->key() == Qt::Key_Up) {
if (event->isAutoRepeat()) return;
keyUp = false; // 释放按键后将标志设置为false
if (move) { // 如果已经完成了移动
move = false; // 设置标志为false
return; // 直接返回
}
if (keyLeft) { // 如果向左方向键已经按下且没有释放
ui->pushButton->move(30, 80); // 斜移
move = true; // 标记已经移动
} else { // 否则直接上移
ui->pushButton->move(120, 80);
}
}
此时再释放向左方向键,在按键释放事件处理函数中会标记keyLeft为假,并且完成了 斜移操作,move此时为真,所以不在操作,将move标记为假
else if (event->key() == Qt::Key_Left) {
if (event->isAutoRepeat()) return;
keyLeft = false;
if (move) {
move = false;
return;
}