事件的分发机制
Qt 的事件分发机制主要依赖于对象的继承关系和事件传递路径。Qt 提供了一套基于 QObject 的事件分发系统,使得事件能够在对象层次结构中传递。
1 事件分发的基本流程
1事件接收:当事件发生时,事件循环会创建一个 QEvent 对象,表示这个事件。
2事件队列:事件被放入目标对象的事件队列。
3事件处理:目标对象接收事件,并决定如何处理它(重绘、响应用户输入等)。
4事件传递:如果事件未被目标对象完全处理,事件可以传递到更高层的对象(如父对象)。
2 事件处理函数
每个 QObject 派生的类都可以通过重写特定的事件处理函数来响应事件。常见的事件处理函数包括:
●bool QWidget::event(QEvent *event):通用事件处理函数,处理所有类型的事件。可以根据事件类型进一步分发。
●void QWidget::mousePressEvent(QMouseEvent *event):处理鼠标按下事件。
●void QWidget::keyPressEvent(QKeyEvent *event):处理键盘按下事件。
●void QWidget::paintEvent(QPaintEvent *event):处理绘图事件。
这些事件处理函数可以被重写,以便在事件发生时执行特定的操作。
3 示例:重写事件处理函数
cpp
#include <QApplication>
#include <QWidget>
#include <QMouseEvent>
#include <QMessageBox>
class MyWidget : public QWidget
{
protected:
void mousePressEvent(QMouseEvent *event) override
{
QMessageBox::information(this, "Mouse Event",
QString("Mouse pressed at (%1, %2)")
.arg(event->x()).arg(event->y()));
}
void paintEvent(QPaintEvent *event) override
{
// 自定义绘图逻辑
QPainter painter(this);
painter.drawText(event->rect(), Qt::AlignCenter, "Hello, Qt!");
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyWidget widget;
widget.resize(300, 200);
widget.show();
return app.exec();
}
重写event函数
我们不仅仅可以重写指定的事件,还可以重写event函数(通用事件处理函数),在event里根据事件类型做出判断,并且进行事件处理。
我们制作一个子部件ChildWidget,重新实现它的PaintEvent,绘制一个红色边框更显眼
然后重写event函数,判断鼠标点击事件弹出消息框
cpp
class ChildWidget : public QLabel
{
public:
ChildWidget(const QString &text, QWidget *parent = nullptr) : QLabel(text, parent)
{
setAlignment(Qt::AlignCenter);
}
protected:
void paintEvent(QPaintEvent * event) override{
// 自定义绘图逻辑
QPainter painter(this);
// 设置背景颜色
//设置画笔
painter.setPen(QPen(Qt::red,2));
// 绘制与控件相同大小的矩形
painter.drawRect(rect());
// 调用基类的 paintEvent
QLabel::paintEvent(event);
}
bool event(QEvent *event) override
{
//如果是鼠标点击事件
if (event->type() == QEvent::MouseButtonPress) {
QMessageBox::information(this, "Child Event", "Child received mouse press event.");
// 返回 false 以允许事件继续传递到父对象
return false;
}
return QLabel::event(event);
}
};
在main.cpp中创建这个ChildWidget,其父窗口为MainWindow,我们试试
cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.resize(800,600);
//创建子部件,父窗口为MainWindow
auto * child_wid = new ChildWidget("click me",&w);
child_wid->setGeometry(100,100,100,50);
//注意show为阻塞函数,所以创建工作要放在show上
w.show();
return a.exec();
}
运行后点击子部件,会看到弹出消息框
