Qt中的事件模型

server/2025/3/3 17:00:43/

Qt中的事件模型

Qt 的事件模型是其核心机制之一,用于处理用户交互(如鼠标点击、键盘输入)以及系统事件(如窗口大小改变、定时器事件等)。以下是 Qt 事件模型的详细介绍:

1. 事件的定义

在Qt 中事件是通过QEvent和其子类来表示的,QEvent是一个抽象基类,定义了事件的基本结构,而具体的事件类型(如鼠标事件、键盘事件、定时器事件等),则通过继承QEvent来实现。

例如:

QMouseEvent:鼠标事件。

QKeyEvent:键盘事件。

QResizeEvent:表示窗口大小改变事件。

QTimerEvent:表示定时器事件。

在QtCreator的帮助中看到,QEvent被很多类继承:

微信截图_20250302142706

2. 事件的产生

事件的产生通常由系统或Qt框架触发。

  • 用户移动鼠标时,系统会生成一个鼠标移动事件。
  • 窗口大小改变时,Qt 会生成一个窗口大小改变事件。
  • 定时器超时时,Qt 会生成一个定时器事件。

3. 事件的传递机制

Qt 的事件模型基于事件的传递和处理机制。事件从产生到被处理,通常会经历以下过程:

3.1 事件的传递链:

事件从产生后,会按照一定的顺序传递给目标对象(通常是窗口或控件),传递顺序如下:

1.事件过滤器(Event Filter):如果某个事件安装了事件过滤器(通过installEventFilter()),事件首先传递给事件过滤器,事件过滤器可以首先对事件进行预处理或者拦截。

2事件处理器(Event Handler):如果事件没有被事件过滤器拦截,它会传递到目标对象的事件处理器。事件处理器是一个虚函数,通常以event()的形式存在。

3.默认事件处理器(Default Event Handler):如果事件没有被目标对象处理,事件会传递给父对象(父窗口)。如果父对象也没有处理事件,最终会传递到 Qt 的默认事件处理器,由 Qt 进行默认处理。

3.2 事件的处理方式

事件的处理方式主要分为以下几种:

1.**事件处理器(event() 函数)**每个QObject派生类都有一个event()对象,用于处理事件,如果需要自定义事件处理逻辑,可以重写该函数。

QObject类有一个event()的虚函数。

微信截图_20250302144601

例如:

  if(e->type() == QEvent::KeyPress){// 自定义键盘处理逻辑QMessageBox::information(nullptr,"键盘被点击","这是一个信息弹窗");// 表示事件已被处理return true;}// 调用父类事件处理器return QWidget::event(e);

2。事件过滤器(eventFilter() 函数):事件过滤器是一个全局的事件处理机制,可以拦截并处理其他对象的事件。通过重写 eventFilter() 函数并安装事件过滤器,可以实现对事件的预处理或拦截。

 class MainWindow : public QMainWindow{public:MainWindow();protected:bool eventFilter(QObject *obj, QEvent *ev) override;private:QTextEdit *textEdit;};MainWindow::MainWindow(){textEdit = new QTextEdit;setCentralWidget(textEdit);textEdit->installEventFilter(this);}bool MainWindow::eventFilter(QObject *obj, QEvent *event){if (obj == textEdit) {if (event->type() == QEvent::KeyPress) {QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);qDebug() << "Ate key press" << keyEvent->key();return true;} else {return false;}} else {// pass the event on to the parent classreturn QMainWindow::eventFilter(obj, event);}}

3.专用事件处理函数

Qt 提供了一些专用的事件处理函数,如 mousePressEvent()keyPressEvent() 等。这些函数是 event() 函数的特例,用于处理特定类型的事件。如果需要处理特定事件,可以重写这些函数。

void mousePressEvent(QMouseEvent* e) override {// 自定义鼠标点击事件处理逻辑
}

4. 事件的类型

Qt 定义了多种事件类型,每种事件类型都有一个唯一的枚举值(QEvent::Type)。以下是一些常见的事件类型:

  • QEvent::KeyPressQEvent::KeyRelease:键盘按下和释放事件。
  • QEvent::MouseButtonPressQEvent::MouseButtonRelease:鼠标按钮按下和释放事件。
  • QEvent::MouseMove:鼠标移动事件。
  • QEvent::Resize:窗口大小改变事件。
  • QEvent::Timer:定时器事件。
  • QEvent::Paint:绘图事件。

在QEvent的源码中有:

enum Type {/*If you get a strange compiler error on the line with None,it's probably because you're also including X11 headers,which #define the symbol None. Put the X11 includes afterthe Qt includes to solve this problem.*/None = 0,                               // invalid eventTimer = 1,                              // timer eventMouseButtonPress = 2,                   // mouse button pressedMouseButtonRelease = 3,                 // mouse button releasedMouseButtonDblClick = 4,                // mouse button double clickMouseMove = 5,                          // mouse moveKeyPress = 6,                           // key pressedKeyRelease = 7,                         // key releasedFocusIn = 8,                            // keyboard focus receivedFocusOut = 9,                           // keyboard focus lostFocusAboutToChange = 23,                // keyboard focus is about to be lostEnter = 10,                             // mouse enters widgetLeave = 11,                             // mouse leaves widgetPaint = 12,                             // paint widgetMove = 13,                              // move widgetResize = 14,                            // resize widgetCreate = 15,                            // after widget creationDestroy = 16,                           // during widget destructionShow = 17,                              // widget is shownHide = 18,                              // widget is hiddenClose = 19,                             // request to close widgetQuit = 20,                              // request to quit applicationParentChange = 21,                      // widget has been reparentedParentAboutToChange = 131,              // sent just before the parent change is doneThreadChange = 22,                      // object has changed threadsWindowActivate = 24,                    // window was activatedWindowDeactivate = 25,                  // window was deactivatedShowToParent = 26,                      // widget is shown to parentHideToParent = 27,                      // widget is hidden to parentWheel = 31,                             // wheel eventWindowTitleChange = 33,                 // window title changedWindowIconChange = 34,                  // icon changedApplicationWindowIconChange = 35,       // application icon changedApplicationFontChange = 36,             // application font changedApplicationLayoutDirectionChange = 37,  // application layout direction changedApplicationPaletteChange = 38,          // application palette changedPaletteChange = 39,                     // widget palette changedClipboard = 40,                         // internal clipboard eventSpeech = 42,                            // reserved for speech inputMetaCall =  43,                         // meta call eventSockAct = 50,                           // socket activationWinEventAct = 132,                      // win event activationDeferredDelete = 52,                    // deferred delete eventDragEnter = 60,                         // drag moves into widgetDragMove = 61,                          // drag moves in widgetDragLeave = 62,                         // drag leaves or is cancelledDrop = 63,                              // actual dropDragResponse = 64,                      // drag accepted/rejectedChildAdded = 68,                        // new child widgetChildPolished = 69,                     // polished child widgetChildRemoved = 71,                      // deleted child widgetShowWindowRequest = 73,                 // widget's window should be mappedPolishRequest = 74,                     // widget should be polishedPolish = 75,                            // widget is polishedLayoutRequest = 76,                     // widget should be relayoutedUpdateRequest = 77,                     // widget should be repaintedUpdateLater = 78,                       // request update() laterEmbeddingControl = 79,                  // ActiveX embeddingActivateControl = 80,                   // ActiveX activationDeactivateControl = 81,                 // ActiveX deactivationContextMenu = 82,                       // context popup menuInputMethod = 83,                       // input methodTabletMove = 87,                        // Wacom tablet eventLocaleChange = 88,                      // the system locale changedLanguageChange = 89,                    // the application language changedLayoutDirectionChange = 90,             // the layout direction changedStyle = 91,                             // internal style eventTabletPress = 92,                       // tablet pressTabletRelease = 93,                     // tablet releaseOkRequest = 94,                         // CE (Ok) button pressedHelpRequest = 95,                       // CE (?)  button pressedIconDrag = 96,                          // proxy icon draggedFontChange = 97,                        // font has changedEnabledChange = 98,                     // enabled state has changedActivationChange = 99,                  // window activation has changedStyleChange = 100,                      // style has changedIconTextChange = 101,                   // icon text has changed.  Deprecated.ModifiedChange = 102,                   // modified state has changedMouseTrackingChange = 109,              // mouse tracking state has changedWindowBlocked = 103,                    // window is about to be blocked modallyWindowUnblocked = 104,                  // windows modal blocking has endedWindowStateChange = 105,ReadOnlyChange = 106,                   // readonly state has changedToolTip = 110,WhatsThis = 111,StatusTip = 112,ActionChanged = 113,ActionAdded = 114,ActionRemoved = 115,FileOpen = 116,                         // file open requestShortcut = 117,                         // shortcut triggeredShortcutOverride = 51,                  // shortcut override requestWhatsThisClicked = 118,ToolBarChange = 120,                    // toolbar visibility toggledApplicationActivate = 121,              // deprecated. Use ApplicationStateChange instead.ApplicationActivated = ApplicationActivate, // deprecatedApplicationDeactivate = 122,            // deprecated. Use ApplicationStateChange instead.ApplicationDeactivated = ApplicationDeactivate, // deprecatedQueryWhatsThis = 123,                   // query what's this widget helpEnterWhatsThisMode = 124,LeaveWhatsThisMode = 125,ZOrderChange = 126,                     // child widget has had its z-order changedHoverEnter = 127,                       // mouse cursor enters a hover widgetHoverLeave = 128,                       // mouse cursor leaves a hover widgetHoverMove = 129,                        // mouse cursor move inside a hover widget// last event id used = 132#ifdef QT_KEYPAD_NAVIGATIONEnterEditFocus = 150,                   // enter edit mode in keypad navigationLeaveEditFocus = 151,                   // enter edit mode in keypad navigation
#endifAcceptDropsChange = 152,ZeroTimerEvent = 154,                   // Used for Windows Zero timer eventsGraphicsSceneMouseMove = 155,           // GraphicsViewGraphicsSceneMousePress = 156,GraphicsSceneMouseRelease = 157,GraphicsSceneMouseDoubleClick = 158,GraphicsSceneContextMenu = 159,GraphicsSceneHoverEnter = 160,GraphicsSceneHoverMove = 161,GraphicsSceneHoverLeave = 162,GraphicsSceneHelp = 163,GraphicsSceneDragEnter = 164,GraphicsSceneDragMove = 165,GraphicsSceneDragLeave = 166,GraphicsSceneDrop = 167,GraphicsSceneWheel = 168,GraphicsSceneLeave = 220,KeyboardLayoutChange = 169,             // keyboard layout changedDynamicPropertyChange = 170,            // A dynamic property was changed through setProperty/propertyTabletEnterProximity = 171,TabletLeaveProximity = 172,NonClientAreaMouseMove = 173,NonClientAreaMouseButtonPress = 174,NonClientAreaMouseButtonRelease = 175,NonClientAreaMouseButtonDblClick = 176,MacSizeChange = 177,                    // when the Qt::WA_Mac{Normal,Small,Mini}Size changesContentsRectChange = 178,               // sent by QWidget::setContentsMargins (internal)MacGLWindowChange = 179,                // Internal! the window of the GLWidget has changedFutureCallOut = 180,GraphicsSceneResize  = 181,GraphicsSceneMove  = 182,CursorChange = 183,ToolTipChange = 184,NetworkReplyUpdated = 185,              // Internal for QNetworkReplyGrabMouse = 186,UngrabMouse = 187,GrabKeyboard = 188,UngrabKeyboard = 189,StateMachineSignal = 192,StateMachineWrapped = 193,TouchBegin = 194,TouchUpdate = 195,TouchEnd = 196,#ifndef QT_NO_GESTURESNativeGesture = 197,                    // QtGui native gesture
#endifRequestSoftwareInputPanel = 199,CloseSoftwareInputPanel = 200,WinIdChange = 203,
#ifndef QT_NO_GESTURESGesture = 198,GestureOverride = 202,
#endifScrollPrepare = 204,Scroll = 205,Expose = 206,InputMethodQuery = 207,OrientationChange = 208,                // Screen orientation has changedTouchCancel = 209,ThemeChange = 210,SockClose = 211,                        // socket closedPlatformPanel = 212,StyleAnimationUpdate = 213,             // style animation target should be updatedApplicationStateChange = 214,WindowChangeInternal = 215,             // internal for QQuickWidget and texture-based widgetsScreenChangeInternal = 216,PlatformSurface = 217,                  // Platform surface created or about to be destroyedPointer = 218,                          // Qt 5: QQuickPointerEvent; Qt 6: unused so farTabletTrackingChange = 219,             // tablet tracking state has changed// GraphicsSceneLeave = 220,WindowAboutToChangeInternal = 221,      // internal for QQuickWidget and texture-based widgetsDevicePixelRatioChange = 222,// 512 reserved for Qt Jambi's MetaCall event// 513 reserved for Qt Jambi's DeleteOnMainThread eventUser = 1000,                            // first user event idMaxUser = 65535                         // last user event id};Q_ENUM(Type)

5. 事件的自定义

Qt 允许开发者自定义事件类型。自定义事件需要继承 QEvent 类,并定义自己的事件类型。例如:

#ifndef QCUSTOMEVENT_H
#define QCUSTOMEVENT_H#include <QObject>
#include<QEvent>class QCustomEvent : public QEvent
{Q_OBJECT
public:explicit QCustomEvent();~QCustomEvent();static const QEvent::Type EventType = static_cast<QEvent::Type>(QEvent::User + 1);signals:
};#endif // QCUSTOMEVENT_H

自定义事件可以通过 QCoreApplication::postEvent()QCoreApplication::sendEvent() 发送。

6. 事件的发送方式

Qt 提供了两种发送事件的方式:

  1. QCoreApplication::sendEvent():同步发送事件,事件会立即被处理,函数返回事件的处理结果。
  2. QCoreApplication::postEvent():异步发送事件,事件会被放入事件队列中,稍后由事件循环处理。

7. 事件循环(Event Loop)

事件循环是 Qt 事件模型的核心,负责从事件队列中取出事件并分发给目标对象。事件循环通过调用 exec() 函数启动,通常在应用程序的主函数中启动:

int main(int argc, char* argv[]) {QApplication app(argc, argv);MainWindow w;w.show();return app.exec(); // 启动事件循环
}

事件循环会不断从事件队列中取出事件,并调用目标对象的事件处理器进行处理。

8. 总结

Qt 的事件模型是一个高效且灵活的机制,通过事件的产生、传递和处理,实现了用户交互和系统事件的响应。开发者可以通过重写事件处理器、安装事件过滤器或自定义事件类型,灵活地扩展和定制 Qt 应用程序的行为。


http://www.ppmy.cn/server/172124.html

相关文章

iOS中的设计模式(六)- 单利模式

引言 在 iOS 开发中&#xff0c;单例模式&#xff08;Singleton Pattern&#xff09;是一种非常常见且实用的设计模式。它通过确保某个类只有一个实例&#xff0c;并提供一个全局的访问点&#xff0c;帮助开发者管理共享资源或提供全局配置。在许多应用场景中&#xff0c;我们…

不要升级,Flutter Debug 在 iOS 18.4 beta 无法运行,提示 mprotect failed: Permission denied

近期如果有开发者的 iOS 真机升级到 18.4 beta&#xff0c;大概率会发现在 debug 运行时会有 Permission denied 的相关错误提示&#xff0c;其实从 log 可以很直观看出来&#xff0c;就是 Dart VM 在初始化时&#xff0c;对内核文件「解释运行&#xff08;JIT&#xff09;」时…

Minio搭建并在SpringBoot中使用完成用户头像的上传

Minio使用搭建并上传用户头像到服务器操作,学习笔记 Minio介绍 minio官网 MinIO是一个开源的分布式对象存储服务器&#xff0c;支持S3协议并且可以在多节点上实现数据的高可用和容错。它采用Go语言开发&#xff0c;拥有轻量级、高性能、易部署等特点&#xff0c;并且可以自由…

计算机毕业设计SpringBoot+Vue.js抗疫物资管理系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

鸿蒙日期格式工具封装及使用

封装 DataFormat.ets /*** param {Date} value* return {string}* example* description 格式化日期*/ export class DataFormat {dateFormat(value: Date): string {const year value.getFullYear();const month value.getMonth() 1;const day value.getDate();return ${y…

当前 Qt 应用程序中无法打开串口,并且没有使用通用的 Modbus 类,可在应用程序添加一个专门的“打开串口”按钮

如果你在当前的 Qt 应用程序中无法打开串口&#xff0c;并且没有使用通用的 Modbus 类&#xff0c;那么你可以考虑为你的应用程序添加一个专门的“打开串口”按钮。以下是如何实现这一点的建议&#xff1a; ### **1. 添加“打开串口”按钮** 在你的 UI 文件&#xff08;mainwi…

RabbitMQ 常见问题

目录 前言 常见错误与解决方案 日志分析 Docker中日志分析 总结 前言 常见错误与解决方案 1. 连接失败 2. 队列阻塞 3. 消息丢失 4. 消费者不消费 5. 资源耗尽 日志分析 1. 配置 RabbitMQ 日志 2.日志文件位置 3. 日志分析工具 4. 分析日志文件 5. 常见日志问题及…

高性能数据分析平台:数据驱动时代的利器

高性能数据分析平台:数据驱动时代的利器 在当今的数字化时代,数据已经成为企业和组织最重要的资产之一。然而,如何高效地存储、处理和分析海量数据,成为了技术人员和数据科学家面临的巨大挑战。为了解决这些问题,高性能数据分析平台应运而生,它们能够帮助我们以更快的速…