Qt 事件系统 #
事件系统概述 #
text
┌─────────────────────────────────────────────────────────────┐
│ Qt 事件处理流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 事件源 │
│ ├── 用户输入(鼠标、键盘) │
│ ├── 系统事件(定时器、窗口) │
│ └── 自定义事件 │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 事件循环 │ QCoreApplication::exec() │
│ │ (Event Loop)│ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 事件分发 │ QCoreApplication::notify() │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 事件处理 │ QWidget::event() │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
事件类型 #
常见事件类型 #
cpp
// 常见事件类型
QEvent::MouseButtonPress // 鼠标按下
QEvent::MouseButtonRelease // 鼠标释放
QEvent::MouseMove // 鼠标移动
QEvent::MouseButtonDblClick // 鼠标双击
QEvent::Wheel // 鼠标滚轮
QEvent::KeyPress // 键盘按下
QEvent::KeyRelease // 键盘释放
QEvent::Shortcut // 快捷键
QEvent::Resize // 大小改变
QEvent::Move // 位置移动
QEvent::Show // 显示
QEvent::Hide // 隐藏
QEvent::Close // 关闭
QEvent::Paint // 绘制
QEvent::FocusIn // 获得焦点
QEvent::FocusOut // 失去焦点
QEvent::Enter // 鼠标进入
QEvent::Leave // 鼠标离开
QEvent::Timer // 定时器
QEvent::User // 用户自定义事件
事件处理 #
重写事件处理函数 #
cpp
class MyWidget : public QWidget
{
Q_OBJECT
protected:
// 重写 event 函数
bool event(QEvent *event) override
{
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Escape) {
// 处理 Escape 键
return true; // 事件已处理
}
}
return QWidget::event(event); // 调用父类处理
}
// 重写具体事件处理函数
void mousePressEvent(QMouseEvent *event) override
{
if (event->button() == Qt::LeftButton) {
qDebug() << "Left button pressed at" << event->pos();
}
QWidget::mousePressEvent(event);
}
void mouseReleaseEvent(QMouseEvent *event) override
{
qDebug() << "Mouse released";
QWidget::mouseReleaseEvent(event);
}
void mouseMoveEvent(QMouseEvent *event) override
{
qDebug() << "Mouse moved to" << event->pos();
QWidget::mouseMoveEvent(event);
}
void keyPressEvent(QKeyEvent *event) override
{
switch (event->key()) {
case Qt::Key_Up:
qDebug() << "Up arrow pressed";
break;
case Qt::Key_Down:
qDebug() << "Down arrow pressed";
break;
default:
QWidget::keyPressEvent(event);
}
}
void keyReleaseEvent(QKeyEvent *event) override
{
qDebug() << "Key released:" << event->key();
QWidget::keyReleaseEvent(event);
}
void paintEvent(QPaintEvent *event) override
{
QPainter painter(this);
painter.fillRect(rect(), Qt::white);
painter.drawText(rect(), Qt::AlignCenter, "Hello Qt");
}
void resizeEvent(QResizeEvent *event) override
{
qDebug() << "New size:" << event->size();
QWidget::resizeEvent(event);
}
void closeEvent(QCloseEvent *event) override
{
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "Confirm",
"Are you sure you want to quit?",
QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes) {
event->accept();
} else {
event->ignore();
}
}
void enterEvent(QEnterEvent *event) override
{
qDebug() << "Mouse entered";
QWidget::enterEvent(event);
}
void leaveEvent(QEvent *event) override
{
qDebug() << "Mouse left";
QWidget::leaveEvent(event);
}
void focusInEvent(QFocusEvent *event) override
{
qDebug() << "Got focus";
QWidget::focusInEvent(event);
}
void focusOutEvent(QFocusEvent *event) override
{
qDebug() << "Lost focus";
QWidget::focusOutEvent(event);
}
void wheelEvent(QWheelEvent *event) override
{
qDebug() << "Wheel delta:" << event->angleDelta();
QWidget::wheelEvent(event);
}
};
鼠标事件详解 #
cpp
void MyWidget::mousePressEvent(QMouseEvent *event)
{
// 获取按钮
Qt::MouseButton button = event->button();
if (button == Qt::LeftButton) {
qDebug() << "Left button";
} else if (button == Qt::RightButton) {
qDebug() << "Right button";
} else if (button == Qt::MiddleButton) {
qDebug() << "Middle button";
}
// 获取同时按下的按钮
Qt::MouseButtons buttons = event->buttons();
if (buttons & Qt::LeftButton && buttons & Qt::RightButton) {
qDebug() << "Both left and right buttons";
}
// 获取位置
QPoint pos = event->pos(); // 相对于控件的坐标
QPoint globalPos = event->globalPosition().toPoint(); // 全局坐标
// 获取修饰键
Qt::KeyboardModifiers modifiers = event->modifiers();
if (modifiers & Qt::ControlModifier) {
qDebug() << "Ctrl is pressed";
}
if (modifiers & Qt::ShiftModifier) {
qDebug() << "Shift is pressed";
}
}
键盘事件详解 #
cpp
void MyWidget::keyPressEvent(QKeyEvent *event)
{
// 获取按键
int key = event->key();
// 常用按键判断
switch (key) {
case Qt::Key_Return:
case Qt::Key_Enter:
qDebug() << "Enter pressed";
break;
case Qt::Key_Escape:
qDebug() << "Escape pressed";
break;
case Qt::Key_Tab:
qDebug() << "Tab pressed";
break;
case Qt::Key_Backspace:
qDebug() << "Backspace pressed";
break;
case Qt::Key_Delete:
qDebug() << "Delete pressed";
break;
case Qt::Key_Space:
qDebug() << "Space pressed";
break;
default:
if (key >= Qt::Key_A && key <= Qt::Key_Z) {
qDebug() << "Letter:" << QChar(key);
}
}
// 获取文本
QString text = event->text();
// 获取修饰键
Qt::KeyboardModifiers modifiers = event->modifiers();
if (modifiers & Qt::ControlModifier) {
qDebug() << "Ctrl+" << key;
}
if (modifiers & Qt::AltModifier) {
qDebug() << "Alt+" << key;
}
// 判断是否自动重复
if (event->isAutoRepeat()) {
qDebug() << "Key auto repeat";
}
}
事件过滤器 #
安装事件过滤器 #
cpp
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget *parent = nullptr) : QWidget(parent)
{
// 为自己安装事件过滤器
installEventFilter(this);
// 为子控件安装事件过滤器
QPushButton *button = new QPushButton("Click", this);
button->installEventFilter(this);
}
protected:
bool eventFilter(QObject *watched, QEvent *event) override
{
if (watched == this) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
qDebug() << "Widget key press:" << keyEvent->key();
return true; // 事件已处理
}
}
if (watched == button) {
if (event->type() == QEvent::MouseButtonPress) {
qDebug() << "Button mouse press intercepted";
return true; // 阻止事件传递
}
}
return QWidget::eventFilter(watched, event);
}
private:
QPushButton *button;
};
应用级事件过滤器 #
cpp
class MyApplication : public QApplication
{
Q_OBJECT
public:
MyApplication(int &argc, char **argv) : QApplication(argc, argv) {}
protected:
bool notify(QObject *receiver, QEvent *event) override
{
// 全局事件拦截
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
qDebug() << "Global key press:" << keyEvent->key();
}
return QApplication::notify(receiver, event);
}
};
自定义事件 #
定义自定义事件 #
cpp
// 自定义事件类型
const QEvent::Type MyEventType = static_cast<QEvent::Type>(QEvent::User + 1);
class MyEvent : public QEvent
{
public:
MyEvent(int value) : QEvent(MyEventType), m_value(value) {}
int value() const { return m_value; }
private:
int m_value;
};
发送自定义事件 #
cpp
// 发送事件(同步)
MyEvent event(42);
QCoreApplication::sendEvent(receiver, &event);
// 发送事件(异步)
MyEvent *event = new MyEvent(42);
QCoreApplication::postEvent(receiver, event);
处理自定义事件 #
cpp
class MyWidget : public QWidget
{
Q_OBJECT
protected:
bool event(QEvent *event) override
{
if (event->type() == MyEventType) {
MyEvent *myEvent = static_cast<MyEvent*>(event);
qDebug() << "Custom event received:" << myEvent->value();
return true;
}
return QWidget::event(event);
}
};
事件接受与忽略 #
cpp
void MyWidget::mousePressEvent(QMouseEvent *event)
{
// 接受事件(默认行为)
event->accept();
// 忽略事件(传递给父控件)
event->ignore();
}
void MyWidget::closeEvent(QCloseEvent *event)
{
if (hasUnsavedChanges()) {
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "Save",
"Save changes before closing?",
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
switch (reply) {
case QMessageBox::Save:
saveChanges();
event->accept();
break;
case QMessageBox::Discard:
event->accept();
break;
case QMessageBox::Cancel:
event->ignore();
break;
}
} else {
event->accept();
}
}
事件传递链 #
text
┌─────────────────────────────────────────────────────────────┐
│ 事件传递链 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 事件产生 │
│ │ │
│ ▼ │
│ 2. QCoreApplication::notify() │
│ │ │
│ ▼ │
│ 3. 应用级事件过滤器 │
│ │ │
│ ▼ │
│ 4. 窗口级事件过滤器 │
│ │ │
│ ▼ │
│ 5. 控件的 event() 函数 │
│ │ │
│ ├── 返回 true → 事件处理完成 │
│ │ │
│ └── 返回 false → 继续传递 │
│ │ │
│ ▼ │
│ 6. 父控件的 event() 函数 │
│ │ │
│ └── 继续向上传递直到顶层 │
│ │
└─────────────────────────────────────────────────────────────┘
下一步 #
现在你已经掌握了事件系统,接下来学习 定时器,了解 Qt 的定时任务处理!
最后更新:2026-03-29