键盘消息和鼠标消息没有什么差异,用法和覆写方法都差不多,可以通过传递的参数判断按下了哪些键,下面代码中有比较详细的示例。其中也介绍了一下定时器消息,当覆写一个定时器消息时,你需要调用 QWidget 的成员函数 startTimer 来启动定时器,它的参数是定时器多长时间运行一次,并且如果有多个定时器时,你还需要知道每个定时器的 ID 是多少,定时器消息因为哪个定时器触发了而运行。这些都在例子中有所体现。

【实现代码】

代码分三个文件,分别为(参考 使用 Qt 构建一个简单的窗体程序 ):

  • main.c:创建应用程序框架,调用 CWidget 窗口的入口函数。
  • CWidget.h:继承 QWidget 类。
  • CWidget.cpp:覆写键盘、定时器等消息函数的实现
1
2
3
4
5
6
7
8
9
10
11
12
#include <QApplication>
#include "cwidget.h"

int main(int argc, char* argv[])
{
QApplication app(argc, argv);

CWidget w;
w.show();

return app.exec();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#ifndef CWIDGET_H
#define CWIDGET_H

#include <QWidget>
#include <QKeyEvent>
#include <QDebug>
#include <QTimerEvent>

class CWidget : public QWidget
{
Q_OBJECT
public:
explicit CWidget(QWidget *parent = 0);

void keyPressEvent(QKeyEvent *);
void keyReleaseEvent(QKeyEvent *);

// 定时器消息,需要 startTimer 才会触发
// 在需要的地方调用 startTimer 即可触发 timerEvent 消息
void timerEvent(QTimerEvent *);

int timerId_1;
int timerId_2;

signals:

public slots:
};

#endif // CWIDGET_H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include "cwidget.h"

CWidget::CWidget(QWidget *parent) : QWidget(parent)
{
// 让定时器开始运行,并记录定时器的id
timerId_1 = startTimer(1000);
timerId_2 = startTimer(1000);
}

void CWidget::keyPressEvent(QKeyEvent *ev)
{
int ret = ev->key();
qDebug() << ret << (char)ret << "is down...";

if (ev->modifiers() == Qt::AltModifier)
{
qDebug() << "alt is down...";
// 按下alt后,根据 timerId 关闭一个定时器
killTimer(timerId_1);
}
}

void CWidget::keyReleaseEvent(QKeyEvent *ev)
{
int ret = ev->key();
qDebug() << ret << (char)ret << "is up...";
}

void CWidget::timerEvent(QTimerEvent *ev)
{
if (ev->timerId() == timerId_1)
{
qDebug() << "timerId 1 is running";
}
else if (ev->timerId() == timerId_2)
{
qDebug() << "timerId 2 is running";
}
}