qt的按键事件机制是这样的。
当你按了一个键是会同时触发keyPressEvent和keyReleaseEvent(反复触发)。
在已经按下一个键的情况下,如果按新的键,则前一个键的keyPressEvent,和keyRelease事件不再触发(会在松开按键时触发keyRelease)。但是,我们实际需要的是想要两个键都能触发按下和抬起事件。整理一下思路,不能反复触发事件了,但是前面提到松开按键时也会触发一次keyRelease事件。所以这个时候我们就可以根据这个特性。创建一个对象来保存这些键的状态,按下则设置这个键的状态为1,抬起则设置状态为0。如果两个键同时被按下,则第一个键是少一次释放事件,如果不释放他的状态就会一直是1。有一个坑,就是同时按下的时候,松开后面按下的键keyRelease事件就不会再触发了,直到第一个键松开会再触发一次。所以我们不能在keyRelease事件里面处理逻辑而是用一个定时器。下面是一个代码片段提供一些思路pressKey可以根据自己的需要去实现
void MainWindow::keyPressEvent(QEvent *e)
{
QKeyEvent *keyEvent=static_cast<QKeyEvent *>(e);
switch(keyEvent->key()){
case Qt::Key_Q:{
pressKey->key1=1;//设置按键1为按下状态
break;
}
case Qt::Key_W:
{
pressKey->key2=1;//设置按键2为按下状态
break;
}
}
if(pressKey->haveKeyDown()&&!m_pTimer->isActive())//如果计时器处于停止状态且有一个键已经被按下(总数>1)则开启计时器
{
m_pTimer->start(TIMER_TIMEOUT); // 重复间隔 REPEAT_RATE = 300 毫秒
}
return QWidget::keyPressEvent(keyEvent);
}
void MainWindow::keyReleaseEvent(QEvent *e)
{
QKeyEvent *keyEvent=static_cast<QKeyEvent *>(e);
switch(keyEvent->key()){
case Qt::Key_Q:
{
pressKey->key1=0;
break;
}
case Qt::Key_W:
{
pressKey->key2=0;
break;
}
}//恢复按键的状态
if(m_pTimer->isActive()&&!pressKey->haveKeyDown())
{
m_pTimer->stop(); // 如果没有键按下停止计时器。
}
e->accept();
return QWidget::keyReleaseEvent(keyEvent);
}
bool MainWindow::event(QEvent *e)
{
if(e->type()==QEvent::KeyPress)
{
keyPressEvent(e);//键盘按下事件
}
if(e->type()==QEvent::KeyRelease)
{
keyReleaseEvent(e);//键盘抬起事件
return true;//阻止事件被分发
}
return QMainWindow::event(e);//将键盘事件分发下去
}
void MainWindow::handleKeyDown(){
if( pressKey->key1==1)
{
qDebug()<<"you press a q";//处理自己的事情
}
if(pressKey->key2==1)
{
qDebug()<<"you press a w";//处理自己的事情
}
}
void MainWindow::initKeyNumber()
{
pressKey->key1=0;
pressKey->key2=0;
}
如果想要判断更多的按键同时按下可以在这个的基础上扩展