编程学习
Qt学习05:Event事件(处理分发传播与过滤)
00 分钟
2023-6-2
2023-11-23
type
status
date
slug
summary
tags
category
icon
password
Email
文章首发于我的个人博客:欢迎大佬们来逛逛

事件系统

The Event System
在Qt中,事件是派生自抽象QEvent类的对象,它表示应用程序内发生的事情或应用程序需要知道的外部活动的结果。事件可以由QObject子类的任何实例接收和处理,但它们与小部件尤其相关。
Qt程序需要在main()函数创建一个QApplication对象,然后调用它的exec()函数。这个函数就是开始Qt的事件循环。在执行exec()函数之后,程序将进入事件循环来监听应用程序的事件,当事件发生时,Qt将创建一个事件对象

事件是如何传递的?

当事件发生时,Qt通过构造适当的QEvent子类的实例来创建一个事件对象来表示它,并通过调用它的event()函数将它交付给QObject的一个特定实例(或它的一个子类)。
这个函数event()不处理事件本身;根据交付的事件类型,它为该特定类型的事件调用事件处理程序,并根据事件是被接受还是被忽略发送响应。
一些事件,如QMouseEvent和QKeyEvent,来自窗口系统;还有一些,比如QTimerEvent,来自其他来源;有些来自应用程序本身。

事件类型

大多数事件类型都有特殊的类,特别是QResizeEvent、QPaintEvent、QMouseEvent、QKeyEvent和QCloseEvent。每个类都是QEvent的子类,并添加特定于事件的函数。例如,QResizeEvent添加了size()和oldSize(),以使小部件能够发现它们的尺寸是如何被更改的。
有些类支持多个实际事件类型。QMouseEvent支持按下鼠标按钮、双击、移动和其他相关操作。
每个事件都有一个关联的类型,在QEvent:: type中定义,这可以用作运行时类型信息的方便来源,以快速确定给定事件对象是从哪个子类构建的。
由于程序需要以各种复杂的方式进行响应,Qt的事件传递机制非常灵活。
  • QCoreApplication::notify()的文档简洁地讲述了整个故事;
  • Qt季刊(Qt Quarterly)的文章《另一个看事件》(Another Look at Events)对它进行了重新梳理,但没有那么简洁。这里我们将对95%的应用程序进行足够的解释。

事件处理

传递事件的通常方式是调用虚函数。例如,QPaintEvent通过调用QWidget::paintEvent()来传递。这个虚函数负责进行适当的响应,通常是重新绘制小部件。如果在虚函数的实现中不执行所有必要的工作,则可以调用基类的实现。

事件处理函数

例如,下面的代码处理自定义按钮控件上的鼠标左键单击,同时将所有其他按钮单击传递给基本QPushButton类:
注意:如果这样做了,按钮的clicked()和pressed()信号将不能被触发!
想要让父类也能够处理左键消息,可以把父类的mousePressEvent放在最后调用(不放在else中)。

鼠标事件

鼠标按下

鼠标释放

鼠标双击

鼠标移动

如果关闭了鼠标跟踪,则只有在移动鼠标时按下鼠标按钮时才会发生鼠标移动事件。如果打开了鼠标跟踪,即使没有按下鼠标按钮,也会发生鼠标移动事件。
按钮是自动追踪鼠标的,但是QWidget是不会的,如果要给QWidget的子类重写鼠标移动,需要使用void setMouseTracking(bool enable)启用鼠标追踪。

鼠标滚轮

返回轮子旋转的相对量,单位为八分之一度。正值表示转轮向前旋转,远离用户;负值表示转轮向后向用户旋转。angleDelta().y()提供自上一个事件以来旋转普通垂直鼠标滚轮的角度。如果鼠标有水平滚轮,angleDelta().x()提供水平鼠标滚轮旋转的角度,否则就是0。有些鼠标允许用户倾斜滚轮来进行水平滚动,有些触摸板支持水平滚动手势;它也会出现在angleDelta().x()中。
大多数鼠标类型的工作步长为15度,在这种情况下,delta值是120的倍数;即120单位* 1/8 = 15度。
然而,有些鼠标的滚轮分辨率更高,发送的delta值小于120单位(小于15度)。为了支持这种可能性,可以累计添加来自事件的增量值,直到达到120的值,然后滚动小部件,或者可以部分滚动小部件以响应每个轮事件。

Example:无边框窗口拖动

在做窗口应用程序时,为了使窗口更简洁,有时候会将窗口setWindowFlag();属性设置为Qt::WindowType::FramelessWindowHint,这时,窗口将不可拖动,但我们可以通过以下代码尝试解决无边框窗体的拖动问题。
步骤:
  1. mousePressEvent时获取鼠标点击的pos局部位置,并且保存
  1. mouseMoveEvent时与该起始位置相减得到移动的位置。
代码:

键盘事件

按键按下

按键释放

Example:按钮移动


窗口事件

窗口关闭

当Qt从窗口系统接收到一个顶级小部件的窗口关闭请求时,将用给定的事件调用此事件处理程序。
默认情况下,接受事件并关闭小部件。您可以重新实现此函数,以更改小部件响应窗口关闭请求的方式。例如,您可以通过在所有事件上调用ignore()来防止窗口关闭。
主窗口应用程序通常使用该函数的重新实现来检查用户的工作是否已保存,并在关闭前请求权限。

窗口隐藏、显示

除隐藏和显示窗口外,窗口最小化会发送窗口隐藏事件,正常显示会发送窗口显示事件。

窗口移动

窗口大小改变

窗口焦点

这个事件处理程序可以在子类中重新实现,以接收小部件的键盘焦点事件(焦点接收)。
小部件通常必须将focuspolicy()设置为Qt::NoFocus以外的东西,以便接收焦点事件。(注意,程序员可以在任何小部件上调用setFocus(),即使是那些通常不接受焦点的小部件。)
默认实现更新小部件(不指定focusPolicy()的窗口除外)。

example: 编辑框颜色改变

重写此 QLineEdit 以实现焦点放到此上面会实现颜色的改变,焦点取消则恢复。

右键菜单

程序状态改变

如果需要检测程序中,某些东西是否发生了改变,可以通过void QWidget::changeEvent(QEvent *event)来检测。
  • 以下是常用事件:
    • QEvent::FontChange
    • QEvent::WindowTitleChange
    • QEvent::IconTextChange
    • QEvent::ModifiedChange
    • QEvent::MouseTrackingChange
    • QEvent::WindowStateChange
  • QEvent::WindowStateChange窗口状态改变为例!

定时器事件

拖拽事件(剪切板)

Drag and Drop
设置QWidget窗口接受拖拽:
之后通过 QMimaData来获得内容:

事件分发

传递事件的通常方式是调用虚函数。例如,QMouseEvent通过调用QWidget::mousePressEvent()来传递。这个虚函数负责进行适当的响应,通常是处理鼠标点击,并发出对应的信号。如果在虚函数的实现中不执行所有必要的工作,则可能需要调用基类的实现。
如果希望替换基类的事件处理函数,则必须自己实现所有内容。但是,如果您只想扩展基类的功能,那么您可以实现您想要的功能,并调用基类来获得您不想处理的任何情况的默认行为。
有时,没有这样一个特定于事件的函数,或者特定于事件的函数是不够的。最常见的例子是按Tab键。通常情况下,QWidget会拦截这些来移动键盘焦点,但也有一些小部件本身需要Tab键。
这些对象可以重新实现QObject::event()(通用事件处理程序),并在通常处理之前或之后执行它们的事件处理,或者它们可以完全替换函数。一个非常不寻常的小部件既解释Tab又具有特定于应用程序的自定义事件,它可能包含以下event()函数:
注意,对于所有未处理的情况,仍然调用QWidget::event(),并且返回值指示是否处理了事件;true值防止事件被发送到其他对象。

Example:无边框窗口拖动

前面通过事件处理函数实现了无边框窗口的拖动,如何通过事件分发函数实现呢?

发送事件

许多应用程序都希望创建和发送它们自己的事件。通过构造合适的事件对象并使用QCoreApplication::sendEvent()QCoreApplication::postEvent()发送事件,您可以以与Qt自己的事件循环完全相同的方式发送事件。
sendEvent()立即处理事件。当它返回时,事件过滤器和/或对象本身已经处理了该事件。对于许多事件类,都有一个名为isAccepted()的函数,它告诉您事件是被最后一个调用的处理程序接受还是拒绝的。
postEvent()将事件发送到队列中,以便稍后进行分派。下次Qt的主事件循环运行时,它会分发所有发布的事件,并进行一些优化。例如,如果有几个调整大小事件,它们将被压缩为一个。同样适用于绘制事件:QWidget::update()调用postEvent(),它通过避免多次重绘来消除闪烁并提高速度。

自定义事件

要创建自定义类型的事件,需要定义一个事件号,该事件号必须大于QEvent::User,并且可能需要继承QEvent的子类,以便传递关于自定义事件的特定信息。有关更多详细信息,请参阅QEvent文档。
  • 定义事件号
  • 定义事件类
  • 发送和处理事件

sendEvent、postEvent区别

sendEvent

sendEvent会让接受事件的对象立即处理事件,处理完成之后函数返回
  • 对于栈区的事件会自动释放(超出作用域释放)
  • 对于堆区的事件需要函数返回之后自己释放 (超出作用域,也不会自动释放)

postEvent

postEvent是把事件提交到事件队列,不管有没有处理事件,都立即返回
  • 必须把事件放在堆区,处理完毕之后自动释放

事件传播

事件分发

Qt的事件产生之后,不是直接传递给了对象的,需要经过一系列的过程。
  1. 事件首先由Qt的ServerApplication去接收来自于外部或内部的一些行为,鼠标点击,键盘输入,时钟事件等,分析并决定送往对应的对象去处理(内部管理机制),最后会调用[virtual] bool QCoreApplication::notify ( QObject * receiver, QEvent * event ) 去处理,当然这个是虚函数,你可以在子类去重新实现它 。
  1. 在notify(…)中,在发给对应的接收者前,会先把消息送给QApplication。所以如果想在你界面的Widget前先处理那些事 件,那么你可以给QApplication对象installEventFilter,然后在对应的eventFilter()里先把这些事件都给过一 遍,然后你可以过滤一些不必要事件。
  1. 如果QApplication没有处理那些事件,然后就是交给事件接收对象了。在这个对象接收前,也可以为这对象加一个事件过滤器,同样是 installEventFilter。
  1. 如果eventFilter没有过滤某些事件,那么就会将事件交给接收者的event()函数(你可以根据不同类型的事件尽情处理),如果event事件在接受者处理后,也不会上传给父类的event,否则会上传进入父类的event。
  1. 默认event()函数根据事件类型会调用不同的事件处理函数,类似mousePressEvent(),keyPressEvent()去分别处理他们。

事件传播

当控件忽略事件时,事件会继续往上传播,这里的传播是指传播给父组件
  • QEvent有 accept()函数 和ignore()函数:
    • accept():本组件处理该事件,这个事件就不会被继续传播给其父组件;
    • ignore():本组件不想要处理这个事件,这个事件会被继续传播给其父组件;
    • 值得注意的是所有的事件默认都是接受的
  • 忽略和接受案例
  • event(),eventFilter()函数返回值作用

事件过滤

有时,对象需要查看(可能还需要拦截)传递给另一个对象的事件。例如,对话框通常想要过滤一些小部件的按键;例如,修改返回键处理。
QObject::installEventFilter()函数通过设置一个事件过滤器来实现这一点,使指定的过滤器对象在其QObject::eventFilter()函数中接收目标对象的事件。事件过滤器在目标对象处理事件之前处理事件,允许它根据需要检查和丢弃事件。可以使用QObject::removeEventFilter()函数删除现有的事件过滤器。
当调用过滤器对象的eventFilter()实现时,它可以接受或拒绝事件,并允许或拒绝对事件的进一步处理。如果所有事件过滤器都允许对事件进行进一步处理(每个返回false),则将事件发送到目标对象本身。如果其中一个停止处理(通过返回true),目标和任何后面的事件过滤器都不会看到事件。
上面的代码展示了截获发送到特定目标小部件的Tab键按下事件的另一种方法。在这种情况下,过滤器处理相关事件并返回true以阻止它们被进一步处理。所有其他事件都被忽略,过滤器返回false,允许通过安装在目标小部件上的任何其他事件过滤器将它们发送到目标小部件。
通过在QApplication或QCoreApplication对象上安装事件过滤器,还可以为整个应用程序筛选所有事件。这种全局事件过滤器在特定于对象的过滤器之前调用。这是非常强大的,但它也减慢了整个应用程序中每个单个事件的事件交付;通常应该使用讨论的其他技术
处理事件有五种不同的方法,以下列出了所有五种方法:
其他技术:
  • 重新实现paintEvent(), mousePressEvent()等。这是最常见、最简单、最强大的方法。
  • 重新实现bool QCoreApplication::notify()。这是非常强大的,提供完全的控制,但是一次只能有一个子类是活动的(就是说不能实现不同方式的处理,因为实例化应用程序对象只能有一个)。
  • 在QCoreApplication::instance()上安装一个事件过滤器。这样的事件过滤器能够处理所有小部件的所有事件,因此它与重新实现notify()一样强大;此外,可以有多个应用程序全局事件过滤器。全局事件过滤器甚至可以看到禁用小部件的鼠标事件。注意,应用程序事件过滤器只对驻留在主线程中的对象调用。
  • 重新实现QObject::event()(像QWidget那样)。如果您这样做,就可以按Tab键,并且可以在任何特定于小部件的事件过滤器之前看到事件。
  • 在对象上安装事件过滤器。这样的事件过滤器获得所有事件,包括Tab和Shift+Tab键按下事件,只要它们不改变焦点小部件。

Example:无边框窗口拖动

前面通过事件处理函数、事件分发实现了无边框窗口的拖动,如何通过事件过滤实现呢?
这是最简单的,在自己类里面重写eventFilter来过滤事件,但是如果我有很多个无边框窗口,都要实现移动,这个方法就不太方便了。
可以先写一个拖拽控件的过滤器对象,然后哪里需要就在那里添加!

事件类型

QEvent::Type

这个枚举类型定义了Qt中有效的事件类型。事件类型和每个类型的专门类如下:
常量
描述
QEvent::None
0
不是一个事件
QEvent::ActionAdded
114
一个新 action 被添加(QActionEvent)
QEvent::ActionChanged
113
一个 action 被改变(QActionEvent)
QEvent::ActionRemoved
115
一个 action 被移除(QActionEvent)
QEvent::ActivationChange
99
Widget 的顶层窗口激活状态发生了变化
QEvent::ApplicationActivate
121
这个枚举已被弃用,使用 ApplicationStateChange 代替
QEvent::ApplicationActivated
ApplicationActivate
这个枚举已被弃用,使用 ApplicationStateChange 代替
QEvent::ApplicationDeactivate
122
这个枚举已被弃用,使用 ApplicationStateChange 代替
QEvent::ApplicationFontChange
36
应用程序的默认字体发生了变化
QEvent::ApplicationLayoutDirectionChange
37
应用程序的默认布局方向发生了变化
QEvent::ApplicationPaletteChange
38
应用程序的默认调色板发生了变化
QEvent::ApplicationStateChange
214
应用程序的状态发生了变化
QEvent::ApplicationWindowIconChange
35
应用程序的图标发生了变化
QEvent::ChildAdded
68
一个对象获得孩子(QChildEvent)
QEvent::ChildPolished
69
一个部件的孩子被抛光(QChildEvent)
QEvent::ChildRemoved
71
一个对象时区孩子(QChildEvent)
QEvent::Clipboard
40
剪贴板的内容发生改变
QEvent::Close
19
Widget 被关闭(QCloseEvent)
QEvent::CloseSoftwareInputPanel
200
一个部件要关闭软件输入面板(SIP)
QEvent::ContentsRectChange
178
部件内容区域的外边距发生改变
QEvent::ContextMenu
82
上下文弹出菜单(QContextMenuEvent)
QEvent::CursorChange
183
部件的鼠标发生改变
QEvent::DeferredDelete
52
对象被清除后将被删除(QDeferredDeleteEvent)
QEvent::DragEnter
60
在拖放操作期间鼠标进入窗口部件(QDragEnterEvent)
QEvent::DragLeave
62
在拖放操作期间鼠标离开窗口部件(QDragLeaveEvent)
QEvent::DragMove
61
拖放操作正在进行(QDragMoveEvent)
QEvent::Drop
63
拖放操作完成(QDropEvent)
QEvent::DynamicPropertyChange
170
动态属性已添加、更改或从对象中删除
QEvent::EnabledChange
98
部件的 enabled 状态已更改
QEvent::Enter
10
鼠标进入部件的边界(QEnterEvent)
QEvent::EnterEditFocus
150
编辑部件获得焦点进行编辑,必须定义 QT_KEYPAD_NAVIGATION
QEvent::EnterWhatsThisMode
124
当应用程序进入“What’s This?”模式,发送到 toplevel 顶层部件
QEvent::Expose
206
当其屏幕上的内容无效,发送到窗口,并需要从后台存储刷新
QEvent::FileOpen
116
文件打开请求(QFileOpenEvent)
QEvent::FocusIn
8
部件或窗口获得键盘焦点(QFocusEvent)
QEvent::FocusOut
9
部件或窗口失去键盘焦点(QFocusEvent)
QEvent::FocusAboutToChange
23
部件或窗口焦点即将改变(QFocusEvent)
QEvent::FontChange
97
部件的字体发生改变
QEvent::Gesture
198
触发了一个手势(QGestureEvent)
QEvent::GestureOverride
202
触发了手势覆盖(QGestureEvent)
QEvent::GrabKeyboard
188
Item 获得键盘抓取(仅限 QGraphicsItem)
QEvent::GrabMouse
186
项目获得鼠标抓取(仅限 QGraphicsItem)
QEvent::GraphicsSceneContextMenu
159
在图形场景上的上下文弹出菜单(QGraphicsScene ContextMenuEvent)
QEvent::GraphicsSceneDragEnter
164
在拖放操作期间,鼠标进入图形场景(QGraphicsSceneDragDropEvent)
QEvent::GraphicsSceneDragLeave
166
在拖放操作期间鼠标离开图形场景(QGraphicsSceneDragDropEvent)
QEvent::GraphicsSceneDragMove
165
在场景上正在进行拖放操作(QGraphicsSceneDragDropEvent)
QEvent::GraphicsSceneDrop
167
在场景上完成拖放操作(QGraphicsSceneDragDropEvent)
QEvent::GraphicsSceneHelp
163
用户请求图形场景的帮助(QHelpEvent)
QEvent::GraphicsSceneHoverEnter
160
鼠标进入图形场景中的悬停项(QGraphicsSceneHoverEvent)
QEvent::GraphicsSceneHoverLeave
162
鼠标离开图形场景中一个悬停项(QGraphicsSceneHoverEvent)
QEvent::GraphicsSceneHoverMove
161
鼠标在图形场景中的悬停项内移动(QGraphicsSceneHoverEvent)
QEvent::GraphicsSceneMouseDoubleClick
158
鼠标在图形场景中再次按下(双击)(QGraphicsSceneMouseEvent)
QEvent::GraphicsSceneMouseMove
155
鼠标在图形场景中移动(QGraphicsSceneMouseEvent)
QEvent::GraphicsSceneMousePress
156
鼠标在图形场景中按下(QGraphicsSceneMouseEvent)
QEvent::GraphicsSceneMouseRelease
157
鼠标在图形场景中释放(QGraphicsSceneMouseEvent)
QEvent::GraphicsSceneMove
182
部件被移动(QGraphicsSceneMoveEvent)
QEvent::GraphicsSceneResize
181
部件已调整大小(QGraphicsSceneResizeEvent)
QEvent::GraphicsSceneWheel
168
鼠标滚轮在图形场景中滚动(QGraphicsSceneWheelEvent)
QEvent::Hide
18
部件被隐藏(QHideEvent)
QEvent::HideToParent
27
子部件被隐藏(QHideEvent)
QEvent::HoverEnter
127
鼠标进入悬停部件(QHoverEvent)
QEvent::HoverLeave
128
鼠标留离开悬停部件(QHoverEvent)
QEvent::HoverMove
129
鼠标在悬停部件内移动(QHoverEvent)
QEvent::IconDrag
96
窗口的主图标被拖走(QIconDragEvent)
QEvent::IconTextChange
101
部件的图标文本发生改变(已弃用)
QEvent::InputMethod
83
正在使用输入法(QInputMethodEvent)
QEvent::InputMethodQuery
207
输入法查询事件(QInputMethodQueryEvent)
QEvent::KeyboardLayoutChange
169
键盘布局已更改
QEvent::KeyPress
6
键盘按下(QKeyEvent)
QEvent::KeyRelease
7
键盘释放(QKeyEvent)
QEvent::LanguageChange
89
应用程序翻译发生改变
QEvent::LayoutDirectionChange
90
布局的方向发生改变
QEvent::LayoutRequest
76
部件的布局需要重做
QEvent::Leave
11
鼠标离开部件的边界
QEvent::LeaveEditFocus
151
编辑部件失去编辑的焦点,必须定义 QT_KEYPAD_NAVIGATION
QEvent::LeaveWhatsThisMode
125
当应用程序离开“What’s This?”模式,发送到顶层部件
QEvent::LocaleChange
88
系统区域设置发生改变
QEvent::NonClientAreaMouseButtonDblClick
176
鼠标双击发生在客户端区域外
QEvent::NonClientAreaMouseButtonPress
174
鼠标按钮按下发生在客户端区域外
QEvent::NonClientAreaMouseButtonRelease
175
鼠标按钮释放发生在客户端区域外
QEvent::NonClientAreaMouseMove
173
鼠标移动发生在客户区域外
QEvent::MacSizeChange
177
用户更改了部件的大小(仅限 OS X)
QEvent::MetaCall
43
通过 QMetaObject::invokeMethod() 调用异步方法
QEvent::ModifiedChange
102
部件修改状态发生改变
QEvent::MouseButtonDblClick
4
鼠标再次按下(QMouseEvent)
QEvent::MouseButtonPress
2
鼠标按下(QMouseEvent)
QEvent::MouseButtonRelease
3
鼠标释放(QMouseEvent)
QEvent::MouseMove
5
鼠标移动(QMouseEvent)
QEvent::MouseTrackingChange
109
鼠标跟踪状态发生改变
QEvent::Move
13
部件的位置发生改变(QMoveEvent)
QEvent::NativeGesture
197
系统检测到手势(QNativeGestureEvent)
QEvent::OrientationChange
208
屏幕方向发生改变(QScreenOrientationChangeEvent)
QEvent::Paint
12
需要屏幕更新(QPaintEvent)
QEvent::PaletteChange
39
部件的调色板发生改变
QEvent::ParentAboutToChange
131
部件的 parent 将要更改
QEvent::ParentChange
21
部件的 parent 发生改变
QEvent::PlatformPanel
212
请求一个特定于平台的面板
QEvent::PlatformSurface
217
原生平台表面已创建或即将被销毁(QPlatformSurfaceEvent)
QEvent::Polish
75
部件被抛光
QEvent::PolishRequest
74
部件应该被抛光
QEvent::QueryWhatsThis
123
如果部件有“What’s This?”帮助,应该接受事件
QEvent::ReadOnlyChange
106
部件的 read-only 状态发生改变
QEvent::RequestSoftwareInputPanel
199
部件想要打开软件输入面板(SIP)
QEvent::Resize
14
部件的大小发生改变(QResizeEvent)
QEvent::ScrollPrepare
204
对象需要填充它的几何信息(QScrollPrepareEvent)
QEvent::Scroll
205
对象需要滚动到提供的位置(QScrollEvent)
QEvent::Shortcut
117
快捷键处理(QShortcutEvent)
QEvent::ShortcutOverride
51
按下按键,用于覆盖快捷键(QKeyEvent)
QEvent::Show
17
部件显示在屏幕上(QShowEvent)
QEvent::ShowToParent
26
子部件被显示
QEvent::SockAct
50
Socket 激活,用于实现 QSocketNotifier
QEvent::StateMachineSignal
192
信号被传递到状态机(QStateMachine::SignalEvent)
QEvent::StateMachineWrapped
193
事件是一个包装器,用于包含另一个事件(QStateMachine::WrappedEvent)
QEvent::StatusTip
112
状态提示请求(QStatusTipEvent)
QEvent::StyleChange
100
部件的样式发生改变
QEvent::TabletMove
87
Wacom 写字板移动(QTabletEvent)
QEvent::TabletPress
92
Wacom 写字板按下(QTabletEvent)
QEvent::TabletRelease
93
Wacom 写字板释放(QTabletEvent)
QEvent::OkRequest
94
Ok 按钮在装饰前被按下,仅支持 Windows CE
QEvent::TabletEnterProximity
171
Wacom 写字板进入接近事件(QTabletEvent),发送到 QApplication
QEvent::TabletLeaveProximity
172
Wacom 写字板离开接近事件(QTabletEvent),发送到 QApplication
QEvent::ThreadChange
22
对象被移动到另一个线程。这是发送到此对象的最后一个事件在上一个线程中,参见:QObject::moveToThread()
QEvent::Timer
1
定时器事件(QTimerEvent)
QEvent::ToolBarChange
120
工具栏按钮在 OS X 上进行切换
QEvent::ToolTip
110
一个 tooltip 请求(QHelpEvent)
QEvent::ToolTipChange
184
部件的 tooltip 发生改变
QEvent::TouchBegin
194
触摸屏或轨迹板事件序列的开始(QTouchEvent)
QEvent::TouchCancel
209
取消触摸事件序列(QTouchEvent)
QEvent::TouchEnd
196
触摸事件序列结束(QTouchEvent)
QEvent::TouchUpdate
195
触摸屏事件(QTouchEvent)
QEvent::UngrabKeyboard
189
Item 失去键盘抓取(QGraphicsItem)
QEvent::UngrabMouse
187
Item 失去鼠标抓取(QGraphicsItem、QQuickItem)
QEvent::UpdateLater
78
部件应该排队在以后重新绘制
QEvent::UpdateRequest
77
部件应该被重绘
QEvent::WhatsThis
111
部件应该显示“What’s This”帮助(QHelpEvent)
QEvent::WhatsThisClicked
118
部件的“What’s This”帮助链接被点击
QEvent::Wheel
31
鼠标滚轮滚动(QWheelEvent)
QEvent::WinEventAct
132
发生了 Windows 特定的激活事件
QEvent::WindowActivate
24
窗口已激活
QEvent::WindowBlocked
103
窗口被模态对话框阻塞
QEvent::WindowDeactivate
25
窗户被停用
QEvent::WindowIconChange
34
窗口的图标发生改变
QEvent::WindowStateChange
105
窗口的状态(最小化、最大化或全屏)发生改变(QWindowStateChangeEvent)
QEvent::WindowTitleChange
33
窗口的标题发生改变
QEvent::WindowUnblocked
104
一个模态对话框退出后,窗口将不被阻塞
QEvent::WinIdChange
203
本地窗口的系统标识符发生改变
QEvent::ZOrderChange
126
部件的 z 值发生了改变,该事件不会发送给顶层窗口
用户事件的值应该介于 QEvent:: 和 QEvent::MaxUser之间。
常量
描述
QEvent::User
1000
用户定义的事件
QEvent::MaxUser
65535
最后的用户事件 ID
为方便起见,可以使用 [static] int QEvent::registerEventType(int *hint* = -1) 函数来注册和存储一个自定义事件类型,这样做会避免意外地重用一个自定义事件类型。

事件和信号的区别

事件(QEvent)
信号(SIGNAL)
与QObject的关系
由具体对象进行处理
由具体对象主动产生
对程序影响
改写事件处理函数可能导致程序行为发生改变
信号是否存在对应的槽函数不会改变程序行为
两者的联系
一般而言,信号在具体的事件处理函数中产生
信号和事件是两个不同层面的东西,发出者不同,作用不同。Qt中,所有的QObject的子类实例均可对事件接收和处理!

自定义按钮

 

本节完整代码


评论
  • Twikoo
  • Valine