无锡网站建,济南网站推广服务,苏州 营销型网站 高端网站,西安网站建设itcandy1. 事件
事件 是一个描述应用程序中、发生的某些事情的对象。
在 Qt 中#xff0c;所有事件都继承自 QEvent #xff0c;并且每个事件都有特定的标识符#xff0c;如#xff1a;Qt::MouseButtonPress 代表鼠标按下事件。
每个事件对象包含该事件的所有相关信息#xff…1. 事件
事件 是一个描述应用程序中、发生的某些事情的对象。
在 Qt 中所有事件都继承自 QEvent 并且每个事件都有特定的标识符如Qt::MouseButtonPress 代表鼠标按下事件。
每个事件对象包含该事件的所有相关信息如鼠标事件包含鼠标的坐标、按下的按钮等信息。
2. 事件处理器
事件处理器 是用于处理特定类型事件的成员函数通常以 event 结尾如mousePressEvent 、enterEvent 等。
事件处理器定义了当某个事件发生时应执行的操作。
事件处理器可以分为两类
预定义事件处理器由 Qt 提供的标准事件处理函数可以通过重写它们以实现自定义行为。
class SessionFriendItem : public QWidget
{Q_OBJECT
public:SessionFriendItem(QWidget* owner, const QIcon avatar, const QString name, const QString text): owner(owner), selected(false){// 1. 设置基本属性和样式this-setFixedHeight(64);this-setStyleSheet(QWidget { background-color: rgb(236, 233, 231); });// 2. 创建网格布局QGridLayout* layout new QGridLayout();layout-setContentMargins(0, 0, 0, 0);layout-setVerticalSpacing(0); // 设置竖直方向间距layout-setHorizontalSpacing(0); // 设置水平方向间距this-setLayout(layout);// 3. 创建头像QPushButton avatar_btn new QPushButton();avatar_btn-setFixedSize(QSize(46, 46));avatar_btn-setIconSize(QSize(46, 46));avatar_btn-setIcon(avatar);avatar_btn-setStyleSheet(QPushButton { border: none; background-color: transparent; });layout-addWidget(avatar_btn, 0, 0, 2, 2);// 4. 创建昵称QLabel* name_label new QLabel();name_label-setText(name);name_label-setFixedHeight(30);name_label-setStyleSheet(QLabel { font-size: 14px; });layout-addWidget(name_label, 0, 2, 1, 6);// 5. 添加预览消息QLabel* msg_label new QLabel();msg_label-setText(text);msg_label-setFixedHeight(25);msg_label-setStyleSheet(QLabel { font-size: 12px; });layout-addWidget(msg_label, 1, 2, 1, 6);}void mousePressEvent(QMouseEvent* event) override{// 1. 恢复兄弟组件的 rgbQObjectList* children this-parent()-children();for (QObject* child : children){if (child-isWidgetType() false) continue;SessionFriendItem* temp dynamic_castSessionFriendItem*(child);if (temp-selected true){temp-selected false;temp-setStyleSheet(QWidget { background-color: rgb(236, 233, 231); });}}// 2. 设置当前组件的 rgbthis-selected true;this-setStyleSheet(QWidget { background-color: rgb(200, 199, 198); });}void enterEvent(QEnterEvent* event) override{// 当前组件被点击则不处理if (selected true) return; this-setStyleSheet(QWidget { background-color: rgb(222, 220, 218); });}void leaveEvent(QEvent* event) override{if (selected true) return;this-setStyleSheet(QWidget { background-color: rgb(236, 233, 231); });}
private:QWidget* owner;bool selected;
};自定义事件处理器处理一些特殊类型的事件可以通过事件过滤器或子类化 QObject 来实现。
3. 事件过滤器
在 Qt 中事件过滤器eventFilter提供了一种机制允许一个对象 监视并处理 另一个对象的事件。
3.1 基本概念
事件过滤器允许拦截发送给某个对象的所有事件并在这些事件被该对象处理之前决定如何处理它们。
步骤
安装事件过滤器通过调用 installEventFilter() 方法将一个对象设置为另一个对象的事件过滤器。重写 eventFilter() 函数在作为事件过滤器的对象中重写 bool eventFilter(QObject* obj, QEvent* event) 函数来定义具体的事件处理逻辑。
3.2 工作原理 QMainWindow 不能直接设置布局需要通过中央部件来管理布局。 this-setCentralWidget() // mainwindow.h
class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent nullptr);~MainWindow();bool eventFilter(QObject* object, QEvent* event) override;QWidget* mainWidget;QPushButton* button;private:Ui::MainWindow *ui;
};// mainwindow.cpp
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui-setupUi(this);mainWidget new QWidget(this);this-setCentralWidget(mainWidget);QVBoxLayout* layout new QVBoxLayout();mainWidget-setLayout(layout);button new QPushButton();button-setText(点击);button-setFixedSize(QSize(50, 50));layout-addWidget(button);// 安装事件过滤器button-installEventFilter(this);
}bool MainWindow::eventFilter(QObject* object, QEvent* event)
{if (object button){if (event-type() QEvent::MouseButtonPress){qDebug() Button_Press;}else if (event-type() QEvent::Enter){qDebug() Button_Enter;}else if (event-type() QEvent::Leave){qDebug() Button_Leave;}// return false; // 允许事件继续传递return true;}// 交给其它事件处理器处理return QMainWindow::eventFilter(object, event);
}鼠标进入按钮上方鼠标点击按钮鼠标离开按钮 installEventFilter 的作用目标 事件过滤器的本质当一个对象 A 调用 installEventFilter(B) 意味着对象 B 会优先接收到对象 A 的事件并可以通过 eventFilter() 方法拦截或处理这些事件。 如果希望在事件滤波器 B 处理完事件后仍然让目标对象 A 继续处理该事件可以在事件滤波器逻辑的末尾 return false。这样事件会继续按照正常的事件处理流程传递下去。 自定义类 能够作为事件过滤器、并被目标对象设置需要确保该类重载了 eventfilter() 方法原生的 Qt 对象如 QWidget无法直接担任事件过滤器的角色因为它们没有提供对 eventfilter() 的重载接口。
4. 事件系统
Qt 的事件系统基于事件驱动模型工作其核心是通过事件队列Event Queue实现异步调用。
以下是其基本运作流程
4.1 事件产生
当用户与应用程序进行交互或系统内部发生某些变化就会产生相应的事件。
所有事件均封装为 QEvent 的子类对象。
例如用户按下鼠标左键会产生一个 QMouseEvent 对象该对象包含了关于鼠标点击的所有信息包括点击的位置、按钮的状态等
键盘按键的按下或释放会产生 QKeyEvent 对象。
4.2 事件传递
对于同步事件 使用 QCoreApplication::sendEvent() 方法时事件会被立即发送给接收者。 发送事件的线程会等待直到事件被完全处理。
对于异步事件 使用 QCoreApplication::postEvent() 方法时生成的事件并非被立即处理而是被放入目标对象所属线程的事件队列中等待调度。 QCoreApplication::exec() 启动的主事件循环会从队列中取出事件进行处理非阻塞并通过 QCoreApplication::notify() 方法来分发该事件到目标对象事件通知确保每个事件都能被正确地发生给它的接收者。 在事件被传递给目标对象之前如果有安装事件过滤器首先会调用这些过滤器的 eventFilter() 方法如果该事件没有被过滤器拦截则继续传递给目标对象。
4.3 事件处理
通过重写 event() 方法或特定的事件处理器如 mousePressEvent() 实现业务逻辑。
如果事件未被处理如未重写 event() 或未调用基类实现某些对象会向父对象传递冒泡机制直至顶层对象。
事件是否传递取决于事件类型和 accept() / ignore() 的标记。
QMouseEvent 默认 accept() QKeyEvent() 默认 ignore() QPaintEvent 仅在目标对象处理、不会传递。
void MainWindow::mousePressEvent(QMouseEvent* event)
{qDebug() button is pressed;event-accept(); // 标记事件已处理// event-ignore(); // 允许事件继续传递
}4.4 事件结束
事件对象会在处理完成后由 Qt 自动销毁除非事件被通过 deleteLater() 标记为 deferred delete。