在 Qt 开发中,事件处理是交互逻辑的核心,绘图则是界面可视化的基础。本文将详细讲解 Qt 中的鼠标事件、定时器事件、绘图事件的处理方式,结合实战代码帮你掌握核心用法。
一、鼠标事件
当鼠标触发点击、移动等操作时,窗口会收到对应的鼠标事件,Qt 通过以Event结尾的事件处理函数响应这些操作,也可通过事件过滤器实现事件拦截。
1. 鼠标点击事件(mousePressEvent)
重写mousePressEvent函数,可获取鼠标点击的坐标和按键类型,并在 Label 上显示相关信息:
cpp
void MyLabel::mousePressEvent(QMouseEvent *ev)
{
// 获取鼠标点击坐标
int x = ev->x();
int y = ev->y();
// 获取点击的按键
Qt::MouseButton btn = ev->button();
QString strButton = "";
if (btn == Qt::LeftButton) strButton = "leftbutton";
if (btn == Qt::RightButton) strButton = "Rightbutton";
if (btn == Qt::MidButton) strButton = "Midbutton";
// Label支持HTML格式显示
QString str = QString("<h1><center>[%1,%2,%3]</center></h1>").arg(x).arg(y).arg(strButton);
this->setText(str);
}
2. 鼠标移动事件(mouseMoveEvent)
鼠标移动事件需注意:ev->buttons()可获取按住的多个按键(位运算判断),而ev->button()仅能获取单次点击的按键。
cpp
void MyLabel::mouseMoveEvent(QMouseEvent *ev)
{
// 获取移动坐标
int x = ev->x();
int y = ev->y();
// 获取按住的按键(支持多按键)
Qt::MouseButtons btns = ev->buttons();
QString strButton = "";
if (btns & Qt::LeftButton) strButton += "leftbutton ";
if (btns & Qt::RightButton) strButton += "Rightbutton ";
if (btns & Qt::MidButton) strButton += "Midbutton ";
// 显示移动信息
QString str = QString("<h1><center>move[%1,%2,%3]</center></h1>").arg(x).arg(y).arg(strButton);
this->setText(str);
}
3. 事件分发(event 函数)
所有事件先进入event函数,可在此拦截 / 重定向事件,返回true表示事件已处理(不再传递),返回false则事件继续传递到父窗口。
cpp
bool MyLabel::event(QEvent *e)
{
// 判断事件类型为鼠标移动
if (e->type() == QEvent::MouseMove) {
this->mouseMoveEvent(static_cast<QMouseEvent*>(e));
return true; // 标记事件已处理
}
// 其他事件交给父类处理
return QLabel::event(e);
}
4. 事件过滤器(eventFilter)
事件过滤器是更灵活的事件拦截方式,需先调用installEventFilter安装过滤器,再重写eventFilter函数:
cpp
// 1. 安装事件过滤器(通常在构造函数中)
this->installEventFilter(this);
// 2. 重写事件过滤函数
bool MyLabel::eventFilter(QObject *watched, QEvent *event)
{
// 拦截鼠标移动事件
if (event->type() == QEvent::MouseMove) {
return true; // 返回true表示拦截事件
}
// 其他事件不拦截
return false;
}
二、定时器事件
定时器事件用于实现定时逻辑,Qt 提供两种定时器实现方式:原生timerEvent和QTimer类(推荐)。
1. 原生定时器(timerEvent)
-
startTimer(int ms):启动定时器,返回定时器 ID,参数为触发间隔(毫秒); -
killTimer(int id):停止指定 ID 的定时器; -
timerEvent(QTimerEvent *ev):定时器事件处理函数,通过ev->timerId()获取定时器 ID。
2. QTimer 类(推荐)
QTimer基于信号槽实现,使用更灵活,核心接口:
cpp
// 创建定时器对象
QTimer *timer = new QTimer(this);
// 设置间隔(毫秒),绑定超时信号
connect(timer, &QTimer::timeout, this, [=]() {
qDebug() << "定时器触发";
});
// 启动定时器
timer->start(1000); // 1秒触发一次
// 停止定时器
// timer->stop();
三、绘图事件(paintEvent)
绘图事件是 Qt 界面绘制的核心,窗口需要重绘时(如首次显示、大小改变)会触发paintEvent函数。
1. 核心绘图组件
|--------------|-----------------|
| 组件 | 作用 |
| QPainter | 画家(执行绘图操作) |
| QPen | 画笔(设置线条样式 / 颜色) |
| QBrush | 画刷(填充封闭图形) |
| QPaintDevice | 绘图设备(窗口 / 图片等) |
2. 基础绘图示例
重写paintEvent函数,实现画线、矩形、椭圆、文字等操作:
cpp
void Widget::paintEvent(QPaintEvent *event)
{
// 创建画家,指定绘图设备为当前窗口
QPainter painter(this);
// 画家偏移(从(100,100)开始绘图)
painter.translate(100, 100);
// 配置画笔(红色、虚线、宽度3)
QPen pen;
pen.setColor(QColor(255, 0, 0));
pen.setStyle(Qt::DashLine);
pen.setWidth(3);
painter.setPen(pen);
// 配置画刷(青色、密集填充)
QBrush brush;
brush.setColor(Qt::cyan);
brush.setStyle(Qt::Dense3Pattern);
painter.setBrush(brush);
// 绘制线条(起点(0,0),终点(100,100))
painter.drawLine(0, 0, 100, 100);
// 绘制矩形(左上角(0,0),宽100,高100)
painter.drawRect(0, 0, 100, 100);
// 绘制圆形(圆心(100,100),半径100)
painter.drawEllipse(QPoint(100, 100), 100, 100);
// 绘制文字
painter.drawText(200, 100, "好好学习,天天向上");
}
3. 手动触发绘图事件
-
repaint():立即触发绘图事件(无优化,多次调用会多次触发); -
update():优化版触发,多次调用仅触发一次(推荐); -
❗注意:禁止在
paintEvent中调用repaint()/update(),会导致无限循环。
4. 绘图设备
Qt 支持多种绘图设备,常用的有:
(1)QPixmap(显示优化)
适合绘制界面图片,支持加载 / 保存:
cpp
QPixmap pix(300, 300);
pix.fill(Qt::white); // 白色填充背景
QPainter painter(&pix);
painter.setPen(QColor(255, 0, 0));
painter.drawEllipse(QPoint(150, 150), 100, 100); // 画圆形
pix.save("D:\\qt\\pix.png"); // 保存图片
(2)QImage(像素级操作)
支持直接修改像素,适合图像处理:
cpp
void Widget::paintEvent(QPaintEvent *event)
{
QImage img;
img.load(":/pix.png"); // 加载图片
// 修改指定区域像素颜色
for (int x = 50; x < 100; x++) {
for (int y = 50; y < 100; y++) {
img.setPixelColor(x, y, QColor(255, 123, 0));
}
}
// 绘制修改后的图片
QPainter painter(this);
painter.drawImage(0, 0, img);
}
(3)QPicture(记录绘图步骤)
可记录QPainter的绘图操作,后续可重现绘制过程,适合动态绘图回放。
总结
本文覆盖了 Qt 中三大核心事件:
-
鼠标事件:通过重写事件函数 / 事件过滤器实现交互;
-
定时器事件:推荐使用
QTimer实现定时逻辑; -
绘图事件:基于
QPainter/QPen/QBrush实现界面绘制,支持多种绘图设备。
掌握这些知识点,可实现 Qt 界面的交互逻辑和自定义绘制,为复杂桌面应用开发打下基础。