88-事件与事件的处理函数-事件的类型与处理函数

事件处理机制和信号/槽机制的区别

信号/槽机制可以说是对事件处理机制的高级封装,如果说事件是用来创建窗口控件的,那么信号与槽就是用来对这个窗口控件进行使用的。

例如,在使用一个按钮时,只需要关注 clicked 信号,不必关注这个按钮如何接收并处理鼠标单击事件,以及发射这个信号。

但是如果要重载一个按钮,就需要关注这个问题。如果要改变它的行为,则在按下鼠标按键时触发 clicked 信号,而不是在释放时触发 clicked 信号。

事件的类型与处理函数

事件的概念

可视化应用程序在接受外界输入设备的输入时,例如鼠标、键盘等的操作,会对输入设备输入的信息进行分类,根据分类的不同,用不同的函数进行处理,做出不同的反应。

外界对 PySide程序进行输人信息的过程称为事件,例如在窗口上单击鼠标、用鼠标拖动窗口在输人框中输人数据等,这些都是外界对程序的输人,都可以称为事件。

PySide 程序对外界的输人进行处理的过程称为事件处理,根据外界输入信息的不同,处理事件的函数也不同。

前面编制的可视化程序中,在主程序中都会创建一个 QApplication 的应用程序实例对象,然后调用实例对象的 exec()函数,这将使应用程序进入一个循环,不断监听外界输入的信息。当输人的信息满足某种分类时,将会产生一个事件对象 QEvent(),事件对象中记录了外界输人的信息,并将事件对象发送给处理该事件对象的函数进行处理。

事件与前面讲过的信号与槽相似,但是又有不同。信号是指控件或窗口本身满足一定条件时,发送一个带数据的信息或不带数据的信息,需要编程人员为这个信息单独写处理这个信息的槽函数,并将信号和槽函数关联,发送信号时,自动执行与之关联的槽函数。而事件是外界对程序的输人,将外界的输人进行分类后交给函数处理,处理事件的函数是固定的,只需要编程人员把处理事件的函数重写,来达到处理外界输入的目的,而不需要将事件与处理事件的函数进行连接,系统会自动调用能处理事件的函数,并把相关数据作为实参传递给处理事件的函数。

下面是一个处理鼠标单击事件的程序,在窗口的空白处单击鼠标左键,在 QLineEdit 控件上显示出鼠标单击点处的窗口坐标值,单击鼠标右键,显示右键单击处屏幕坐标值。

单击鼠标左键或右键将会产生QMouseEvent 事件,QMouseEvent事件的实例对象中有与鼠标事件相关的属性,如 button()方法获取单击的是左键还是右键,x()和 y()方法取鼠标单击点处窗口坐值,globalX()和 globalY()方法获取鼠标单击点处屏幕坐标值。

QWidget窗口处理 QMouseEvent 事件的函数有:

  • mouseDoubleClickEvent(QMouseEvent)
  • mouseMoveEvent(QMouseEvent)
  • mousePressEvent(QMouseEvent)
  • mouseReleaseEvent(QMouseEvent)
  • moveEvent(QMoveEvent)
# -*- coding: UTF-8 -*-
# File date: Hi_2023/3/1 20:31
# File_name: 01-简单的鼠标点击事件.py
import PySide6.QtGui
from PySide6.QtWidgets import QApplication,QWidget,QLabel
from PySide6.QtCore import Qt
import sys


class MyWindow(QWidget):
    def __init__(self,parent=None):
        super().__init__(parent)

        self.resize(500,500)
        self.qlabel = QLabel(self)
        self.qlabel.setGeometry(15,5,500,30)
        self.qlabel.setText("请点击")

    def mousePressEvent(self,event: PySide6.QtGui.QMouseEvent)-> None:  # 重写处理mousePress 事件的函数
        super().mousePressEvent(event)

        template1 ="单击点的窗口坐标是x:{} y:{}"
        template2 ="单击点的屏幕坐标是x:{} y:{}"

        if event.button()== Qt.LeftButton:  # button()获取键或右键
            string = template1.format(event.position().x(),event.position().y())# x()和()获取窗口坐标
            self.qlabel.setText(string)

        if event.button()== Qt.RightButton:  # globalX()和globalY()获取全局坐标
            string = template2.format(event.globalPosition().x(),event.globalPosition().y())
            self.qlabel.setText(string)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = MyWindow()

    win.show()
    sys.exit(app.exec())

QEvent类

官方文档

QEvent类是所有事件的基类,它在 QtCore 模块中。

外界输人给序的信息首先交给QEvent 进行分类,得到不同类型的事件,然后系统将事件及相关信息交给控件或窗口的事件处理函数进行处理,得到对外界输人的响应QEvent 类的属性只有 accepted。

Qt的主事件循环(exec())从事件队列中获取本机窗口系统事件,将它们转换为QEvents,并将转换后的事件发送给QObjects。
通常,事件来自底层窗口系统(自发性()返回true),但也可以使用sendEvent()和postEvent()手动发送事件(自发性(()返回false)。
QObjects通过调用其event()函数来接收事件。该函数可以在子类中重新实现,以自定义事件处理并添加额外的事件类型;event()是一个值得注意的例子。默认情况下,事件被调度到timerEvent()和mouseMoveEvent()等事件处理程序。installEventFilter()允许一个对象拦截去往另一个对象的事件。
基本的QEvent只包含一个事件类型参数和一个"accept"标志。accept标志用accept()设置,并用ignore()清除。它是默认设置的,但不要依赖于此,因为子类可能会选择在其构造函数中清除它。
QEvent的子类包含描述特定事件的附加参数。

常用方法

常用方法如表所示,主要方法介绍如下:

QEvent的方法及参数类型 返回值的类型 说明
setAccepted(accepted: bool) None 设置事件是否被接受
accept() None 事件被接受
设置事件对象的accept标志,相当于调用setAccepted(true)。
设置accept参数表示事件接收器想要该事件。不需要的事件可能会传播到父窗口小部件。
clone() QEvent 重写该函数,返回事件的复本
创建并返回此事件的相同副本。
ignore() None 事件被拒绝
清除事件对象的accept标志参数,相当于调用setAccepted(false)。
清除accept参数表示事件接收器不想要该事件。不需要的事件可能会传播到父窗口小部件。
isAccepted() bool 事件是否被接受
isInputEvent() bool 如果事件对象是QInputEvent或其子类之一,则返回true。
isPointerEvent() bool 如果事件对象是QPointerEvent或其子类之一,则返回true。
isSinglePointEvent() bool 是 QSinglePointEvent事件时返回True
spontaneous() bool 获取事件是否立即被处理
如果事件源自应用程序外部(系统事件),则返回true;否则返回false。
type() QEvent.Type 获取事件的类型
[static]registerEventType([hint=-1]) int 注册新的事件类型
注册并返回自定义事件类型。如果提供的提示可用,将使用它,否则它将返回一个介于User和MaxUser之间的值,该值尚未注册。如果提示的值不在User和MaxUser之间,则会忽略该提示。
如果已获取所有可用值或程序正在关闭,则返回-1。
  • 用accept()或 setAccepted(True)方法接受一个事件
  • 用ignore()或 setAccepted(False)方法拒绝一个事件。
  • 被接受的事件不会再传递给其他对象;被拒绝的事件会传递给其他对象处理,如果没有对象处理,则该事件会被丢弃。
  • 如果事件被QWidget的event()函数进行了处理则用spontaneous()方法的返回值是True,否则返回值是False。
  • event()函数根据事件类型起到分发事件到指定处理函数的作用,可以在event()函数中对事件进行处理
    • 用registerEventType(hint:int=-1)方法可以注册一个新事件类型其中hint的取值介于QEventUser(1000)和 QEvent.MaxUser(65535)之间,返回新事件的D号。
事件类型PySide6.QtCore.QEvent.Type

用type()方法可以返回事件的类型。QEvent中定义了事件的类型,QEent定义的主要事件类型如表所示:

PySide6.QtCore.QEvent.Type
(继承)此枚举类型定义 Qt 中的有效事件类型。事件类型和每种类型的专用类如下所示:enum.IntEnum

Constant Description
QEvent.None 不是一个事件。
QEvent.ActionAdded 激活扩展器已添加新操作()。QActionEvent
QEvent.ActionChanged 操作已更改()。QActionEvent
QEvent.ActionRemoved 已删除一个操作(QActionEvent)。
QEvent.ActivationChange 小部件的顶级窗口激活状态已更改。
QEvent.ApplicationActivate 此枚举已被弃用。请改用ApplicationStateChange。
QEvent.ApplicationActivated 此枚举已被弃用。请改用ApplicationStateChange。
QEvent.ApplicationDeactivate 此枚举已被弃用。请改用ApplicationStateChange。
QEvent.ApplicationFontChange 默认应用程序字体已更改。
QEvent.ApplicationLayoutDirectionChange 默认的应用程序布局方向已更改。
QEvent.ApplicationPaletteChange 默认的应用程序选项板已更改。
QEvent.ApplicationStateChange 应用程序的状态已更改。
QEvent.ApplicationWindowIconChange 应用程序的图标已更改。
QEvent.ChildAdded 一个对象得到一个子对象(QChildEvent)。
QEvent.ChildPolished 一个小部件的子级被抛光(QChildEvent)。
QEvent.ChildRemoved 一个对象失去了一个子对象(QChildEvent)。
QEvent.Clipboard 剪贴板内容已更改。
QEvent.Close 小部件已关闭(QCloseEvent)。
QEvent.CloseSoftwareInputPanel 一个小部件想要关闭软件输入面板(SIP)。
QEvent.ContentsRectChange 小部件内容矩形的边距发生了变化。
QEvent.ContextMenu 上下文弹出菜单(QContextMenuEvent)。
QEvent.CursorChange 小部件的光标已更改。
QEvent.DeferredDelete 对象在清理后将被删除(QDeferredDeleteEvent)
QEvent.DragEnter 光标在拖放操作(QDragEnterEvent)期间进入一个小部件。
QEvent.DragLeave 在拖放操作(QDragLeaveEvent)期间,光标会离开一个小部件。
QEvent.DragMove 正在进行拖放操作(QDragMoveEvent)。
QEvent.Drop 拖放操作已完成(QDropEvent)。
QEvent.DynamicPropertyChange 已向对象添加、更改或删除动态属性。
QEvent.EnabledChange 小工具的启用状态已更改。
QEvent.Enter 鼠标进入小部件的边界(QEnterEvent)。
QEvent.EnterEditFocus 编辑器小部件获得编辑的焦点。必须定义QT_KEYPAD_NAMEVIGATION。
QEvent.EnterWhatsThisMode 当应用程序进入"What’s This?"模式时,发送到顶层窗口小部件。
QEvent.Expose 当窗口的屏幕内容无效并且需要从后台存储中清除时,发送到窗口。
QEvent.FileOpen 文件打开请求(QFileOpenEvent)。
QEvent.FocusIn 小工具或窗口获得键盘焦点(QFocusEvent)。
QEvent.FocusOut 小工具或窗口失去键盘焦点(QFocusEvent)。
QEvent.FocusAboutToChange 小工具或窗口焦点即将更改(QFocusEvent)
QEvent.FontChange 小工具的字体已更改。
QEvent.Gesture 触发了一个手势(QEstureEvent)。
QEvent.GestureOverride 触发了手势覆盖(QEstureEvent)。
QEvent.GrabKeyboard 项目获得键盘抓取(仅限QGraphicsItem)。
QEvent.GrabMouse 物品获得鼠标抓取(仅限QGraphicsItem)。
QEvent.GraphicsSceneContextMenu 图形场景上的上下文弹出菜单(QGraphicsSceneContextMenuEvent)。
QEvent.GraphicsSceneDragEnter 光标在拖放操作(QGraphicsSceneDragDropEvent)期间进入图形场景。
QEvent.GraphicsSceneDragLeave 在拖放操作(QGraphicsSceneDragDropEvent)期间,光标会离开图形场景。
QEvent.GraphicsSceneDragMove 正在对场景进行拖放操作(QGraphicsSceneDragDropEvent)。
QEvent.GraphicsSceneDrop 在场景上完成拖放操作(QGraphicsSceneDragDropEvent)。
QEvent.GraphicsSceneHelp 用户请求图形场景的帮助(QHelpEvent)。
QEvent.GraphicsSceneHoverEnter 鼠标光标进入图形场景中的悬停项目(QGraphicsSceneHoverEvent)。
QEvent.GraphicsSceneHoverLeave 鼠标光标会在图形场景中留下悬停项目(QGraphicsSceneHoverEvent)。
QEvent.GraphicsSceneHoverMove 鼠标光标在图形场景中的悬停项目内移动(QGraphicsSceneHoverEvent)。
QEvent.GraphicsSceneMouseDoubleClick 在图形场景(QGraphicsSceneMouseEvent)中再次按下鼠标(双击)。
QEvent.GraphicsSceneMouseMove 在图形场景中移动鼠标(QGraphicsSceneMouseEvent)。
QEvent.GraphicsSceneMousePress 在图形场景中按下鼠标(QGraphicsSceneMouseEvent)。
QEvent.GraphicsSceneMouseRelease 在图形场景中释放鼠标(QGraphicsSceneMouseEvent)。
QEvent.GraphicsSceneMove 小部件已移动(QGraphicsSceneMoveEvent)。
QEvent.GraphicsSceneResize 已调整小部件的大小(QGraphicsSceneResizeEvent)。
QEvent.GraphicsSceneWheel 鼠标滚轮在图形场景中滚动(QGraphicsSceneWheelEvent)。
QEvent.GraphicsSceneLeave 光标将离开图形场景(QGraphicsSceneWheelEvent)。
QEvent.Hide 小工具已隐藏(QHideEvent)。
QEvent.HideToParent 一个子窗口小部件已被隐藏。
QEvent.HoverEnter 鼠标光标进入一个悬停小部件(QOverEvent)。
QEvent.HoverLeave 鼠标光标离开一个悬停小部件(QOverEvent)。
QEvent.HoverMove 鼠标光标在悬停小部件(QOverEvent)内移动。
QEvent.IconDrag 窗口的主图标已被拖走(QIconDragEvent)。
QEvent.IconTextChange 小工具的图标文本已更改。(已弃用)
QEvent.InputMethod 正在使用输入方法(QInputMethodEvent)。
QEvent.InputMethodQuery 输入法查询事件(QInputMethodQueryEvent)
QEvent.KeyboardLayoutChange 键盘布局已更改。
QEvent.KeyPress 按键按下(QKeyEvent)。
QEvent.KeyRelease 按键释放(QKeyEvent)。
QEvent.LanguageChange 应用程序翻译已更改。
QEvent.LayoutDirectionChange 布局的方向已更改。
QEvent.LayoutRequest 小工具布局需要重做。
QEvent.Leave 鼠标离开小部件的边界。
QEvent.LeaveEditFocus 编辑器小部件在编辑时失去焦点。必须定义QT_KEYPAD_NAMEVIGATION。
QEvent.LeaveWhatsThisMode 当应用程序离开"What’s This?"模式时,发送到顶层小部件。
QEvent.LocaleChange 系统区域设置已更改。
QEvent.NonClientAreaMouseButtonDblClick 在客户端区域外发生鼠标双击(QMouseEvent)。
QEvent.NonClientAreaMouseButtonPress 在客户端区域外发生鼠标按键按下(QMouseEvent)。
QEvent.NonClientAreaMouseButtonRelease 客户端区域外发生鼠标按钮释放(QMouseEvent)。
QEvent.NonClientAreaMouseMove 在客户端区域外发生鼠标移动(QMouseEvent)。
QEvent.MacSizeChange 用户更改了小部件的大小(仅限macOS)。
QEvent.MetaCall 通过invokeMethod()进行的异步方法调用。
QEvent.ModifiedChange 小工具修改状态已更改。
QEvent.MouseButtonDblClick 再次按下鼠标(QMouseEvent)。
QEvent.MouseButtonPress 鼠标按下(QMouseEvent)。
QEvent.MouseButtonRelease 鼠标释放(QMouseEvent)。
QEvent.MouseMove 鼠标移动(QMouseEvent)。
QEvent.MouseTrackingChange 鼠标跟踪状态已更改。
QEvent.Move 小工具的位置已更改(QMoveEvent)。
QEvent.NativeGesture 系统检测到一个手势(QNativeGestureEvent)。
QEvent.OrientationChange 屏幕方向发生变化(QScreenOrientationChangeEvent)。
QEvent.Paint 需要屏幕更新(QPaintEvent)。
QEvent.PaletteChange 小部件的调色板已更改。
QEvent.ParentAboutToChange 小部件父级即将更改。
QEvent.ParentChange 小部件父级已更改。
QEvent.PlatformPanel 已请求一个特定于平台的面板。
QEvent.PlatformSurface 已创建或即将销毁本机平台表面(QPlatformSurfaceEvent)。
QEvent.Polish 小部件经过抛光处理。
QEvent.PolishRequest 应该对小部件进行抛光处理。
QEvent.QueryWhatsThis 如果小部件有"What’s This?"帮助(QHelpEvent),那么它应该接受该事件。
QEvent.Quit 应用程序已退出。
QEvent.ReadOnlyChange 小部件的只读状态已更改。
QEvent.RequestSoftwareInputPanel 一个小部件想要打开一个软件输入面板(SIP)。
QEvent.Resize 小部件的大小已更改(QResizeEvent)。
QEvent.ScrollPrepare 对象需要填写其几何体信息(QScrollPrepareEvent)。
QEvent.Scroll 对象需要滚动到提供的位置(QScrollEvent)。
QEvent.Shortcut 按下子项以进行快捷键处理(QShortcutEvent)。
QEvent.ShortcutOverride 按键输入子项,用于覆盖快捷键处理(QKeyEvent)。当快捷方式即将触发时,ShortcutOverride将发送到活动窗口。这允许客户端(例如小部件)通过接受事件来发出信号,表明他们将自己处理快捷方式。如果接受快捷方式覆盖,则事件将作为正常按键传递到焦点小部件。否则,它会触发快捷操作(如果存在的话)。
QEvent.Show 小部件已显示在屏幕上(QShowEvent)。
QEvent.ShowToParent 已经显示了一个子窗口小部件。
QEvent.SockAct 套接字已激活,用于实现QSocketNotifier。
QEvent.StateMachineSignal 一种传递到状态机的信号(QStateMachine::SignalEvent)。
QEvent.StateMachineWrapped 该事件是另一个事件(QStateMachine::WrappedEvent)的包装器,即包含该事件。
QEvent.StatusTip 请求状态提示(QStatusTipEvent)。
QEvent.StyleChange 小工具的样式已更改。
QEvent.TabletMove 表格移动(QTabletEvent)。
QEvent.TabletPress 表格按下(QTabletEvent)。
QEvent.TabletRelease 表格释放(QTabletEvent).
QEvent.TabletEnterProximity 进入表格事件(QTabletEvent),发送至QApplication。
QEvent.TabletLeaveProximity 离开表格事件(QTabletEvent),发送至QApplication。
QEvent.TabletTrackingChange 表格跟踪状态已更改。
QEvent.ThreadChange 对象被移动到另一个线程。这是上一个线程中发送到此对象的最后一个事件。请参见moveToThread()。
QEvent.Timer 定时事件(QTimerEvent)。
QEvent.ToolBarChange 在macOS上切换工具栏按钮。
QEvent.ToolTip 请求了工具提示(QHelpEvent)。
QEvent.ToolTipChange 小部件的工具提示已更改。
QEvent.TouchBegin 触摸屏或触控板事件序列的开始(QTouchEvent)。
QEvent.TouchCancel 取消触摸事件序列(QTouchEvent)。
QEvent.TouchEnd 触摸结束事件序列(QTouchEvent)。
QEvent.TouchUpdate 触摸屏事件(QTouchEvent)。
QEvent.UngrabKeyboard 项目丢失键盘抓取(仅QGraphicsItem)。
QEvent.UngrabMouse 项目丢失鼠标抓取(QGraphicsItem,QQuickItem)。
QEvent.UpdateLater 小部件应该排队等待以后重新绘制。
QEvent.UpdateRequest 应该重新绘制小部件。
QEvent.WhatsThis 小部件应该显示"这是什么?"帮助(QHelpEvent)。
QEvent.WhatsThisClicked 点击了小部件"这是什么?"帮助中的链接。
QEvent.Wheel 鼠标滚轮滚动(QWheelEvent)。
QEvent.WinEventAct 发生了Windows特定的激活事件。
QEvent.WindowActivate 窗口已激活。
QEvent.WindowBlocked 该窗口被模式对话框阻止。
QEvent.WindowDeactivate 窗口已停用。
QEvent.WindowIconChange 窗口的图标已更改。
QEvent.WindowStateChange 窗口的状态(最小化、最大化或全屏)已更改(QWindowStateChangeEvent)。
QEvent.WindowTitleChange 窗口标题已更改。
QEvent.WindowUnblocked 退出模式对话框后,窗口将被取消阻止。
QEvent.WinIdChange 此本机小部件的窗口系统标识符已更改。
QEvent.ZOrderChange 小部件的z顺序已更改。此事件从不发送到顶级窗口。
事件类

PySide/PyQt 是对 Qt的封装,Qt 程序是事件驱动的,它的每个动作都由幕后的某个事件触发有些事件类型类支持多种动作触发方式,如QMouseEvent 支持鼠标按键按下双击、移动等相关操作。事件来源比较广泛,一些事件来自窗口系统(如QMouseEvent和OKeyEvent),一些事件来自其他来源(如QtimerEvent),有些事件来自应用程序本身。常见的 Qt事件如下。

  • 键盘事件:按键按下和松开
  • 鼠标事件:鼠标指针移动、鼠标按键按下和松开
  • 拖放事件:用鼠标进行拖放
  • 滚轮事件:用鼠标滚轮滚动。
  • 绘屏事件:重绘屏幕的某些部分。
  • 定时事件:定时器到时。
  • 焦点事件:键盘焦点移动。
  • 进入事件和离开事件:鼠标指针移入 Widget 内,或者移出移动事件:Widget的位置改变。
  • 大小改变事件:Widget 的大小改变显示事件和隐藏事件:Widget 的显示和隐藏窗口事件:窗口是否为当前窗口。

还有一些常见的 Qt 事件,如 Socket 事件、剪贴板事件、字体改变事件、布局改变事件等。
Qt中所有的事件类型如表所示。

事件类型 描 述
QtGui.QShortcutEvent QShortcutEvent 类提供了一个在用户按下组合键时生成的事件
QtGui.QWindowStateChangeEvent QWindowStateChangeEvent 类在窗口状态更改之前提供窗口状态
QtGui.QTouchEvent QTouchEvent 类包含描述触摸事件的参数
QtGui.QScrollPrepareEvent 发送 QScrollPrepareEvent类以准备滚动
QtGui.QScrollEvent 滚动时发送 QScrollEvent 类
QtGui.QPointingDevice QPointingDevice类描述了鼠标、触摸或平板电脑事件源自的设备
QtGui.QPointingDeviceUniqueId QPointingDeviceUniqueld标识一个唯一的对象,如标记的令牌或手写 笔,它与定点设备(PointingDevice)一起使用
QtGui.QShortcut QShortcut类用于创建键盘快捷键
QtWidgets.QGestureEvent QGestureEvent 类提供触发手势的描述
QtCore.QEvent QEvent类是所有事件类的基类。事件对象包含参数
QtCore.QTimerEvent QTimerEvent类包含描述计时器事件的参数
QtCore.QChildEvent QChildEvent类包含子对象事件的参数
QtCore.QDynamicPropertyChangeEvent QDynamicPropertyChangeEvent 类包含动态属性更改事件的参数
QtCore.QTimer QTimer类提供重复和单次定时器
QtGui.QEnterEvent QEnterEvent类包含描述输入事件的参数
QtGui.QInputEvent QInputEvent 类是描述用户输入的事件的基类
QtGui.QMouseEvent QMouseEvent类包含描述鼠标事件的参数
QtGui.QHoverEvent QHoverEvent 类包含描述鼠标事件的参数
QtGui.QWheelEvent QWheelEvent类包含描述鼠标滚轮事件的参数
QtGui.QKeyEvent QKeyEvent类描述了一个按键事件
QtGui.QFocusEvent QFocusEvent 类包含小部件焦点事件的参数
QtGui.QPaintEvent QPaintEvent类包含绘制事件的参数
QtGui.QMoveEvent QMoveEvent类包含移动事件的参数
QtGui.QExposeEvent QExposeEvent类包含用于公开事件的参数
QtGui.QPlatformSurfaceEvent QPlatformSurfaceEvent类用于通知本机platform surface相关事件
QtGui.QResizeEvent QResizeEvent类包含调整大小事件的参数
QtGui.QCloseEvent QCloseEvent类包含描述关闭事件的参数
QtGui.QIconDragEvent QIconDragEvent类指示主图标拖动已开始
QtGui.QContextMenuEvent QContextMenuEvent类包含描述上下文菜单事件的参数
QtGui.QInputMethodEvent QInputMethodEvent类为输入法事件提供参数
QtGui.QTabletEvent QTabletEvent 类包含描述平板电脑事件的参数
QtGui.QNativeGestureEvent QNativeGestureEvent类包含描述手势事件的参数
QtGui.QDropEvent QDropEvent类提供了一个在拖放操作完成时发送的事件
QtGui.QDragEnterEvent QDragEnterEvent类提供了一个事件,当拖放操作进入小部件时,该事 件被发送到小部件
QtGui.QDragMoveEvent QDragMoveEvent类提供了一个在拖放操作正在进行时发送的事件
QtGui.QDragLeaveEvent QDragLeaveEvent类提供了一个事件,当拖放操作离开小部件时,该事 件被发送到小部件
QtGui.QHelpEvent QHelpEvent 类提供了一个事件,用于请求有关小部件中特定点的有用 信息
QtGui.QStatusTipEvent QStatusTipEvent类提供了一个用于在状态栏中显示消息的事件
QtGui.QWhatsThisClickedEvent QWhatsThisClickedEvent 类提供了一个事件,可以用于处理"这是什 么?"中的超链接、文本
QtGui.QActionEvent QActionEvent类提供了在添加、删除或更改QAction时生成的事件
QtGui.QHideEvent QHideEvent类提供了一个在小部件隐藏后发送的事件
QtGui.QShowEvent QShowEvent类提供了在显示小部件时发送的事件
QtGui.QFileOpenEvent QFileOpenEvent类提供了一个事件,当请求打开文件或 URL时将发送 该事件
QtGui.QShortcutEvent QShortcutEvent类提供了一个在用户按下组合键时生成的事件
QtGui.QWindowStateChangeEvent QWindowStateChangeEvent类在窗口状态更改之前提供窗口状态
QtGui.QTouchEvent QTouchEvent类包含描述触摸事件的参数
QtGui.QScrollPrepareEvent 发送QScrollPrepareEvent类以准备滚动
QtGui.QScrollEvent 滚动时发送 QScrollEvent类
QtGui.QPointingDevice QPointingDevice 类描述了鼠标、触摸或平板电脑事件源自的设备
QtGui.QPointingDeviceUniqueId QPointingDeviceUniqueld标识一个唯一的对象,如标记的令牌或手写 笔,它与定点设备(PointingDevice)一起使用
QtGui.QShortcut QShortcut类用于创建键盘快捷键
QtWidgets.QGestureEvent QGestureEvent 类提供触发手势的描述
常用事件

窗口或控件中用于常用事件的处理函数及参数类型如表所示,传递的参数是对应类的实例对象,参数所代表的类的使用方法在后续内容中进行介绍

常用事件的处理函数及参数类型 说 明
actionEvent(QActionEvent) 当增加、插人、删除QAction时调用该函数
changeEvent(QEvent) 状态发生改变时调用该函数,事件类型包括:
QEvent.ToolBarChange
QEvent.ActivationChange
QEvent.EnabledChange
QEvent.FontChange
QEvent.StyleChange
QEvent.PaletteChange
QEvent.WindowTitleChange
QEvent.IconTextChange
QEvent.ModifiedChange
QEvent.MouseTrackingChange
QEvent.ParentChange
QEvent.WindowStateChange
QEvent.LanguageChange
QEvent.LocaleChange
QEvent.LayoutDirectionChange
QEvent.ReadOnlyChange
childEvent(QChildEvent) 容器控件中添加或移除控件时调用该函数
closeEvent(QCloseEvent) 关闭窗口时调用该函数
contextMenuEvent(QContextMenuEvent) 当窗口或控件的contextMenuPolicy 属性值是 Qt.DefaultContextMenu,单击右键弹出右键菜单时调用该函数
dragEnterEvent(QDragEnterEvent) 用鼠标拖拽物体进入窗口或控件时调用该函数
dragLeaveEvent(QDragLeaveEvent) 用鼠标拖拽物体离开窗口或控件时调用该函数
dragMoveEvent(QDragMoveEvent) 用鼠标拖拽物体在窗口或控件中移动时调用该函数
dropEvent(QDropEvent) 用鼠标拖拽物体在窗口或控件中释放时调用该函数
enterEvent(QEnterEvent) 光标进人窗口或控件时调用该函数
focusInEvent(QFocusEvent) 用键盘使窗口或控件获得焦点时调用该函数
focusOutEvent(QFocusEvent) 用键盘使窗口或控件失去焦点时调用该函数
hideEvent(QHideEvent) 隐藏或最小化窗口时调用该函数
inputMethodEvent(QInputMethodEvent) 输人方法的状态发生改变时调用该数
keyPressEvent(QKeyEvent) 按下键盘的按键时调用该函数
keyReleaseEvent(QKeyEvent) 释放键盘的按键时调用该函数
leaveEvent(QEvent) 光标离开窗口或控件时调用该函数
mouseDoubleClickEvent(QMouseEvent) 双击鼠标时调用该函数
mouseMoveEvent(QMouseEvent) 光标在窗口或控件中移动时调用该函数
mousePressEvent(QMouseEvent) 按下鼠标的按键时调用该函数
mouseReleaseEvent(QMouseEvent) 释放鼠标的按键时调用该函数
moveEvent(QMoveEvent) 移动窗口或控件时调用该函数
paintEvent(QPaintEvent) 控件或窗口需要重新绘制时调用该函数
resizeEvent(QResizeEvent) 窗口或控件的尺寸(长度或宽度)发生改变时调用该函数
showEvent(QShowEvent) 显示窗口或从最小化恢复到原窗口状态时调用该函数 .
tabletEvent(QTabletEvent) 平板电脑处理事件
timerEvent(QTimerEvent) 用窗口或控件的 startTimer(interval: int,timerType:Qt.CoarseTimer)方法启动一个定时器时调用该函数
wheelEvent(QWheelEvent) 转动鼠标的滚轮时调用该函数

每个窗口或控件的功能是不同的,因此窗口和控件的事件也不同,用于处理事件的函数也不同。

下面介绍的窗口或常用控件的事件处理函数如表所示。要调用窗口或控件的事件处理函数,需要继承窗口类或控件类创建其子类,在子类中重写事件处理函数。

窗口或控件 窗口或控件的事件处理函数
QWidget actionEvent()
changeEvent()
closeEvent()
contextMenuEvent()
dragEnterEvent()
dragLeaveEvent()
dragMoveEvent()
dropEvent()
enterEvent()
focusInEvent()
focusOutEvent()
hideEvent()
inputMethodEvent()
keyPressEvent()
leaveEvent()
keyReleaseEvent()
mouseDoubleClickEvent()
mouseMoveEvent()
showEvent()
mousePressEvent()
mouseReleaseEvent()
moveEvent()
paintEvent()
event()resizeEvent()
tabletEvent()
wheelEvent()
QMainWindo contextMenuEvent()
event()
QDialog showEvent()
closeEvent()
contextMenuEvent()
eventFilter()
keyPressEvent()
resizeEvent()
QLabel changeEvent()
contextMenuEvent()
event()
focusInEvent()
focusutEvent()
keyPressEyent()
mouseMoveEvent()
mousePressEvent()
mouseReleaseEvent()
paintEyent()
QLineEdit changeEvent()
contextMenuEvent()
dragEnterEvent()
dragleaveEvent()
dragMoveEvent()
dropEvent()
focusInEvent()
focusutEvent()
paintEvent()
inputMethodEvent()
keyPressEvent()
keyReleaseEvent()
mouseMoveEvent()
mouseDoubleClickEvent()
mousePressEvent()
rouseReleaseEvent()
QTextEdit changeEvent()
contextMenuEvent()
dragEnterEvent()
dragLeaveEvent()
dragMoveEvent()
dropEvent()
focusInEvent()
focusCutEvent()
showEvent()
inputMethodEvent()
keyPressEvent()
keyReleaseEvent()
resizeEvent()
mouseDoubleClickEvent()
mouseMoyeEvent()
mousePressEvent()
paintEvent()
mouseReleaseEvent()
wheelEvent()
QPlainTextEdit changeEvent()
contextMenuEvent()
dragEnterEvent()
dragLeaveEvent()
dragMoveEvent()
dropEvent()
focusInEvent()
focusOutEvent()
paintEvent()
inputMethodEvent()
keyPressEvent()
keyReleaseEvent()
resizeEvent()
mouseDoubleClickEvent()
mouseMoveEvent()
mousePressEvent()
showEvent()
mouseReleaseEvent()
wheelEvent()
QTextBrowser event()
focusOutEvent()
keyPressEvent()
mouseMoveEvent()
paintEvent()
mousePressEvent()
mouseReleaseEvent()
QComboBox changeEvent()
contextMenuEvent()
focusInEvent()
focusOutEvent()
hideEvent()
inputMethodEvent()
keyPressEvent()
keyReleaseEvent()
musePressEvent()
mouseReleaseEvent()
paintEvent()
resizeEvent()
showEvent()
wheelEvent()
QScrollBar event()
contextMenuEvent()
hideEvent()
mouseMoveEvent()
paintEvent()
mousePressEvent()
mouseReleaseEvent()
wheelEvent()
QSlider event()
mouseMoveEvent()
mousePressEvent()
mouseReleaseEvent()
paintEvent()
QDial event()
mouseMoveEvent()
mousePressEvent()
mouseReleaseEvent()
paintEvent()
resizeEvent()
QProgressBar event()
paintEvent()
QPushButton event()
focusInEvent()
focusOutEvent()
keyPressEvent()
mouseMoveEvent()
paintEvent()
QCheckBox event()
mouseMoveEvent()
paintEvent()
QRadioButton event()
mouseMoveEvent()
paintEvent()
OCalendarWidget event()
eventFilter(t)
keyPressEvent()
mousePressEvent()
resizeEvent()
QLCDNumber event()
paintEvent()
QDateTimeEdit focusInEvent()
keyPressEvent()
mousePressEvent()
paintEvent()
wheelEvent()
QGroupBox changeEvent()
childEvent(QChildEvent)
event()
focusInEvent()
resizeEvent()
mouseMoveEvent()
mousePressEvent()
mouseReleaseEvent()
paintEvent()
QFrame changeEvent()
event()
paintEvent()
QScrollArea event()
eventFilter(QObject,
QEvent)
resizeEvent()
QTabWidget changeEvent()
event()
keyPressEvent()
paintEvent()
resizeEvent()
showEvent()
QToolBox changeEvent()
closeEvent()
event()
paintEvent()
QSplitter childEvent(QChildEvent)
event()
eventFilter()
paintEvent()
resizeEvent()
showEvent()
timerEvent()
viewportEvent()
QWebEngineView closeEvent()
contextMenuEvent()
dragEnterEvent()
dragLeaveEvent()
dragMoveEvent()
dropEvent()
event()
hideEvent()
showEvent()
QDockWidget changeEvent()
closeEvent()
event()
paintEvent()
QMdiArea childEvent(QChildEvent)
event()
eventFilter()
paintEvent()
resizeEvent()
showEvent()
timerEvent()
viewportEvent()
QMdiSubWindow changeEvent()
childEvent(QChildEvent)
closeEvent()
contextMenuEvent()
event()
eventFilter()
focusInEvent()
focusOutEvent()
hideEvent()
timerEvent()
keyPressEvent()
leaveEvent()
mouseDoubleClickEvent()
mouseMoveEvent()
mousePressEvent()
mouseReleaseEvent()
moveEvent()
paintEvent()
resizeEvent()showEvent()
QToolButton actionEvent()
changeEvent()
enterEvent()
event()
leaveEvent()
timerEvent()
mousePressEvent()
mouseReleaseEvent()
paintEvent()
QToolBar actionEvent()
changeEvent()
event()
paintEvent()
QMenuBar actionEvent()
changeEvent()
event()
eventFilter()
focusnEvent()
leaveEvent()
focusOutEvent()
keyPressEvent()
nouseMoveEvent()
mousePressEvent()
mouseReleaseEvent()
paintEvent()
resizeEvent()
timerEvent(QTimerEvent)
QStatusBar event()
paintEvent()
resizeEvent()
showEvent()
QTabBar changeEvent()event()
hideEvent()
keyPressEvent()
mouseDoubleClickEvent()
mouseMoveEvent()
mousePressEyent()
ouseReleaseEvent()
paintEyent()
resizeEvent()
showEvent()
timerEyent(QTimerEvent)
wheelEvent()
QListWidget dropEvent()
event()
QTableWidget dropEvent()
event()
QTreeWidget dropEvent()
event()
QListView dragLeaveEvent()
dragMoveEvent()
dropEvent()
event()
mouseMoveEvent()
mouseReleaseEvent()
paintEvent()
resizeEvent()
timerEvent(QTimerEvent)
wheelEvent()
QTreeView changeEvent()
dragMoveEvent()
keyPressEvent()
mouseDoubleClickEvent()
mouseMoveEvent()
mousePressEvent()
mouseReleaseEvent()
paintEvent()
timerEvent(QTimerEvent)
viewportEvent()
QTableView paintEyent()
timerEvent(QTimerEvent)
QVideoWidget event()
hideEvent()
moveEvent()
resizeEvent()
showEvent()
QGraphicsView contextMenuEvent()
dragEnterEvent()
dragLeaveEvent()
ragMoveEvent()
dropEvent()
event()
focusInEvent()
focusOutEvent()
inputMethodEvent()
keyPressEvent()
keyReleaseEvent()
mouseDoubleClickEvent()
paintEvent()
mouseMoveEyent()
mousePressEyent()
mouseReleaseEvent()
resizeEvent()
showEvent()
viewportEvent()
wheelEvent()
QGraphicsScene event()
focusInEyent()
focusOutEvent()
keyPressEvent()
keyReleaseEvent()
eventFilter(QObject,
QEvent)
inputMethodEvent()
helpEvent(QGraphicsSceneHelpEvent)
wheelEvent(QGraphicsSceneWheelEvent)
contextMenuEvent(QGraphicsSceneContextMenuEvent)
dragEnterEyent(QGraphicsSceneragDropEvent)
dragleaveEvent(QGraphicsSceneDragDropEvent)
dragMoveEvent(QGraphicsSceneDragDropEvent)
dropEvent(QGraphicsSceneDragDropEvent)
mouseDoubleClickEvent(QCraphicsSceneMouseEvent)
mouseMoveEvent(QGraphicsSceneMouseEvent)
mousePressEvent(QGraphicsSceneMouseEvent)
mouseReleaseEvent(QGraphicsSceneMouseEvent)
QGraphicsWidget changeEyent()
closeEvent()
hideEvent()
showEvent()
polishEvent()
grabKeyboardEvent(QEvent)
grabMouseEvent(QEvent)
ungrabKeyboardEventQEvent)
ungrabMouseEvent(QEvent)
windowFrameEvent(QEvent)
moveEventQGraphicsSceneMoveEvent)
rasizeEvent(QGraphicsSceneResizeEvent)
QGraphicsItem focusInEvent()
focusOutEvent()
inputMethodEvent()
keyPressEvent()
QEvent()
keyReleaseEvent()
sceneEvent()
dropEvent(QGraphicsSceneDragDropEvent)
sceneEventFilter(QGraphicsItem,
QEvent)
wheelEvent(QGraphicsSceneWheelEvent)
contextMenuEvent(QGraphicsSceneContextMenuEvent)
dragEnterEvent(QGraphicsSceneDragDropEvent)
dragLeaveEvent(QGraphicsSceneDragDropEvent)
dragMoveEvent(QGraphicsSceneDragDropEvent)
hoverEnterEvent(QGraphicsSceneHoverEvent)
hoverLeaveEvent(QGraphicsSceneHoverEvent)
hoverMoveEvent(QGraphicsSceneHoverEvent)
mouseDoubleClickEvent(GraphicsSceneMouseEvent)
mouseMoveEvent(QGraphicsSceneMouseEvent)
mousePressEvent(QGraphics-SceneMouseEvent)
mouseReleaseEvent(QGraphicsSceneMoGseEvent)
QEvent子类事件汇总
事件 描述
QGraphicsSceneEvent 当QGraphicsView接收到Qt鼠标、键盘和拖放事件(QMouseEvent、QKeyEvent、QDragEvent等)时,它会将它们转换为QGraphicsSceneEvent子类的实例,并将它们转发到它显示的QGraphicsSene。然后,场景将事件转发到相关项目。
例如,当QGraphicsView接收到类型为MousePress的QMouseEvent作为对用户单击的响应时,该视图会通过其mousePressEvent()函数向底层QGraphicsScene发送类型为GraphicsSceneMousePress的QgraphicsSceneMuseEvent。默认的mousePressEvent()实现确定单击了哪个项目,并将事件转发到mousePressEvents()。
QGraphicsSceneMouseEvent和QGraphicsSceneContextMenuEvent等子类在屏幕、场景和项目坐标中提供原始QEvent的坐标(请参见screenPos()、scenePos()和pos())。项目坐标由QGraphicsScene在将事件转发到QGraphicsItem之前设置。鼠标事件还增加了从视图接收的最后一个事件中检索坐标的可能性(请参见lastScreenPos()、lastScenePos()和lastPos(())。
QGraphicsSceneWheelEvent QGraphicsSceneWheelEvent类在图形视图框架中提供轮子事件。
QGraphicsView接收到的QWheelEvent被翻译成QGraphicsSceneWheelEvents;它将QWheelEvent::globalPos()转换为项目、场景和屏幕坐标(pos()、scenePos()和screenPos())。
QGraphicsSceneResizeEvent 当QGraphicsWidget的几何图形发生变化时,它会立即向自己发送一个QGraphicsSceneResizeEvent。
它类似于QResizeEvent,但其大小oldSize()和newSize()使用QSizeF而不是QSize。
QGraphicsSceneMoveEvent 当QGraphicsWidget的本地位置发生变化时,它会立即向自己发送一个QGraphicsSceneMoveEvent。交付是作为itemChange()的一部分实现的。
它类似于QMoveEvent,但它的位置oldPos()和newPos(()使用QPointF而不是QPoint。
QGraphicsSceneMouseEvent 当QGraphicsView接收到QMouseEvent时,它会将其转换为QGraphicsSceneMouseEvent。然后,该事件被转发到与视图关联的QGraphicsScene。如果事件未由场景处理,则视图可能会使用它,例如用于DragMode。
除了包含事件的项目、场景和屏幕坐标(如pos()、scenePos()和screenPos())外,鼠标事件还包含视图接收到的上一个鼠标事件的坐标。这些可以使用lastPos()、lastScreenPos(()和lastScenePos()进行检索。
QGraphicsSceneHoverEvent 当QGraphicsView接收到QOverEvent事件时,它会将其转换为QGraphicsSceneHoverEvent。然后,该事件被转发到与视图关联的QGraphicsScene。
QGraphicsSceneHelpEvent 当QGraphicsView接收到ToolTip类型的QEvent时,它会创建一个QGraphicsSceneHelpEvent,并将其转发到场景。您可以使用setToolTip()在QGraphicsItem上设置工具提示;默认情况下,QGraphicsScene在鼠标位置下显示具有最高z值(即最上面的项目)的QGraphicsItem的工具提示。
QGraphicsView在请求"What’s This"和状态提示帮助时不转发事件。如果需要,可以重新实现viewportEvent(),并将类型为WhatsThis的QStatusTipEvent事件和QEvents转发到场景。
QGraphicsSceneDragDropEvent QGraphicsView继承了QWidget提供的拖放功能。当它接收到拖放事件时,它会将其转换为QGraphicsSceneDragDropEvent。
QGraphicsSceneDragDropEvent存储GraphicsScenedDragEnter、GraphicsScened DragLeave、GraphicsSsceneDragMove或GraphicsSceneDrop类型的事件。
QGraphicsSceneDragDropEvent包含鼠标光标在项目、场景和屏幕坐标中的位置;这可以通过pos()、scenePos()和screenPos()进行检索。
该场景将事件发送到鼠标光标下接受放置的第一个QGraphicsItem;使用setAcceptDrops()将图形项设置为接受放置。
QGraphicsSceneContextMenuEvent QGraphicsView接收到的QContextMenuEvent被转换为QGraphicsSceneContextMenuEvents。globalPos()被转换为项、场景和屏幕坐标(pos()、scenePos()和screenPos())。
QGestureEvent QGestureEvent类包含一个手势列表,可以使用gestures()函数获取该列表。
手势要么处于活动状态,要么已取消。可以使用activeGestures()函数获取当前正在执行的操作的列表。可以使用canceledGestures()函数访问以前处于活动状态并已被取消的列表。例如,如果当前窗口失去焦点,或者由于超时或其他原因,手势可能会被取消。
如果事件处理程序不通过调用泛型accept()函数来接受事件,则所有未被接受且处于GestureStarted状态的QEsture对象都将向上传播到父小部件链,直到小部件通过为每个对象调用accept(。
WrappedEvent 包装事件
SignalEvent 信号事件
QWindowStateChangeEvent QWindowStateChangeEvent类提供窗口状态更改之前的窗口状态
QWhatsThisClickedEvent QWhatsThisClickedEvent类提供了一个事件,可用于处理"What’s This?"文本中的超链接。
QToolBarChangeEvent 工具栏更改事件
QStatusTipEvent QStatusTipEvent类提供了一个用于在状态栏中显示消息的事件。
可以使用setStatusTip()函数在小部件上设置状态提示。当鼠标光标进入小部件时,它们会显示在状态栏中。例如:
def __init__(self,parent):
super().__init__(parent)
88-事件与事件的处理函数-事件的类型与处理函数_第1张图片
还可以使用setStatusTip()函数对操作设置状态提示:
def init(self,parent):
super().init(parent)
fileMenu = menuBar().addMenu(tr(“File”))
newAct = QAction(tr(“New”),self)
newAct.setStatusTip(tr(“Create a file().”))
fileMenu.addAction(newAct)
88-事件与事件的处理函数-事件的类型与处理函数_第2张图片
最后,通过StatusTipRole枚举值支持项视图类的状态提示。
QShowEvent QShowEvent类提供了一个在显示小部件时发送的事件。
演出事件有两种:由窗口系统引起的演出事件(自发的)和内部演出事件。自发性(自发性())显示事件在窗口系统显示窗口后立即发送;当顶级窗口在被图标化后被重新显示时,它们也被发送。内部显示事件在窗口小部件可见之前交付。
QShortcutEvent QShortcutEvent类提供了一个在用户按下组合键时生成的事件。
通常情况下,您不需要直接使用此类;QShortcut提供了一个更高级别的界面来处理快捷键。
QScrollPrepareEvent QScrollPrepareEvent类是在准备滚动时发送的。
滚动准备事件在滚动(通常由QScroller)开始之前发送。接收此事件的对象应设置viewportSize、maxContentPos和contentPos。它还应该接受这个事件来指示应该开始滚动。
不能保证在接受的QScrollPrepareEvent之后发送QScrollEvent,例如在最大内容位置为(0,0)的情况下。
QScrollEvent QScrollEvent类在滚动时发送。
发送滚动事件以指示接收器应该被滚动。通常,接收器应该是像QWidget或QGraphicsObject这样的可视对象。
应注意,不会从两个来源发送冲突的QScrollEvents。然而,使用scrollTo是保存的。
QResizeEvent QResizeEvent类包含用于调整大小事件的事件参数。
调整大小事件将发送到已调整大小的小部件。
事件处理程序resizeEvent()接收调整大小事件。
QPlatformSurfaceEvent QPlatformSurfaceEvent类用于通知本机平台表面事件。
当窗口和屏幕外表面的底层原生表面被创建或即将被销毁时,平台窗口事件会同步发送到它们。
应用程序可以响应这些事件,以了解底层平台表面何时存在。
QPaintEvent QPaintEvent类包含绘制事件的事件参数。
绘制事件被发送到需要更新自己的小部件,例如,当一个小部件的一部分由于覆盖小部件被移动而暴露时。
该事件包含一个需要更新的region()和一个rect(),后者是该区域的边界矩形。两者都是因为许多小部件无法充分利用region(),而rect()的速度可能比region(()快得多。boundingRect()。
自动剪裁
在绘制事件的处理过程中,绘制被剪裁到region()。该剪裁由Qt的绘制系统执行,并且独立于可以应用于用于在绘制设备上绘制的QPainter的任何剪裁。
因此,clipRegion()在新构建的QPainter上返回的值将不会反映绘制系统使用的剪辑区域。
QMoveEvent QMoveEvent类包含移动事件的事件参数
移动事件被发送到已经被移动到相对于其父窗口小部件的新位置的窗口小部件。
事件处理程序moveEvent()接收移动事件。
QInputMethodQueryEvent QInputMethodQueryEvent类提供由输入上下文发送给输入对象的事件
输入法使用它来查询对象的一组属性,以便能够支持复杂的输入法操作,如支持周围的文本和重新转换。
queries()指定要查询的属性。
在调用accept()之前,对象应该对事件调用setValue()来填充请求的数据。
QInputMethodEvent QInputMethodEvent类为输入方法事件提供参数。当使用输入法在小部件中输入文本时,输入法事件被发送到小部件。输入法被广泛用于输入具有非拉丁字母的语言的文本。
请注意,在创建自定义文本编辑小部件时,必须显式设置WA_InputMethodEnabled窗口属性(使用setAttribute()函数),以便接收输入方法事件。
键盘输入小部件的作者对这些事件很感兴趣,他们希望能够正确处理具有复杂字符输入的语言。用这种语言输入文本通常需要三个步骤:
- 开始创作
当用户按下键盘上的第一个键时,就会创建一个输入上下文。此输入上下文将包含一个键入字符的字符串。
- 合成
每按下一个新键,输入法都会尝试为迄今为止键入的文本创建一个匹配的字符串,称为preedit字符串。当输入上下文处于活动状态时,用户只能在属于该输入上下文的字符串内移动光标。
- 在某个时刻,用户将激活一个用户界面组件(可能使用特定的键),在那里他们可以从与迄今为止键入的文本匹配的多个字符串中进行选择。用户可以确认他们的选择,也可以取消输入;在任何一种情况下,输入上下文都将被关闭。

QInputMethodEvent对这三个阶段进行建模,并传输正确呈现中间结果所需的信息。QInputMethodEvent有两个主要参数:preeditString()和commitString()。preeditString()参数提供当前活动的preedit字符串。commitString()参数给出了一个文本,该文本应添加到编辑器小部件的文本中(或替换其部分)。它通常是输入操作的结果,必须直接插入到preedit字符串之前的窗口小部件文本中。
如果commitString()应该替换编辑器中的部分文本,那么replacementLength()将包含要替换的字符数。replacementStart()包含要替换的字符相对于预编辑字符串开头的位置。
许多属性控制预编辑字符串的视觉外观(预编辑字符串外文本的视觉外观仅由小部件控制)。AttributeType枚举描述了可以设置的不同属性。
实现inputMethodEvent()或inputMethodEvent的类至少应该理解并尊重TextFormat和Cursor属性。
由于输入方法需要能够从小部件或图形项中查询某些属性,因此子类还必须分别实现inputMethodQuery()和inputMethodQuery。
当接收到输入法事件时,文本小部件必须执行以下步骤:
- 如果小部件已选择文本,则应删除所选文本。
- 用length replacementLength()删除从replacementStart()开始的文本,并用commitString()替换它。如果replacementLength()为0,那么replacementStart()将给出commitString()的插入位置。
- 当进行替换时,预编辑字符串的区域被忽略,因此从-1开始、长度为2的替换将删除预编辑字符串之前的最后一个字符和之后的第一个字符,并将提交字符串直接插入预编辑字符串前面。
- 如果小部件实现了undo/redo,则此操作将被添加到undo堆栈中。
- 如果当前没有preedit字符串,请在当前光标位置插入preeditString();否则,将先前的preeditString替换为从此事件中接收到的preeditString。
- 如果小部件实现了undo/redo,那么preeditString()不应该以任何方式影响undo/redo堆栈。
- 小部件应该检查要应用于preedit字符串的属性列表。它必须至少理解TextFormat和Cursor属性,并按照指定进行渲染。
QInputEvent QInputEvent类是描述用户输入的事件的基类
QPointerEvent 指针事件的基类。
QTouchEvent QTouchEvent类包含描述触摸事件的参数。
启用触摸事件#
当按下、释放或移动触摸设备(如触摸屏或触控板)上的一个或多个触摸点时,会发生触摸事件。要接收触摸事件,小部件必须设置WA_AcceptTouchEvents属性,图形项目需要将AcceptTouchEvents设置为true。
使用基于QAbstractScrollArea的小部件时,应在滚动区域的视口上启用WA_AcceptTouchEvents属性。
与QMouseEvent类似,Qt在小部件内第一次按下时自动抓取每个触摸点,小部件将接收该触摸点的所有更新,直到它被释放。注意,小部件可以接收多个触摸点的事件,并且多个小部件可以同时接收触摸事件。

事件处理
所有触摸事件都属于TouchBegin、TouchUpdate、TouchEnd或TouchCancel类型。窗口小部件的重新实现事件()或viewportEvent(),以及图形视图中接收触摸事件的项目的sceneEvent()。
与窗口小部件不同,QWindows总是接收触摸事件,不需要选择加入。当直接使用QWindow时,重新实现touchEvent()就足够了。
TouchUpdate和TouchEnd事件被发送到接受TouchBegin事件的小部件或项目。如果TouchBegin事件未被接受且未被事件过滤器过滤,则在下一次TouchBegin之前不会发送进一步的触摸事件。
某些系统可能会发送类型为TouchCancel的事件。在接收到该事件时,请求应用程序忽略整个活动触摸序列。例如,在合成的系统中,合成器可以决定将某些手势视为系统范围的手势。无论何时做出这样的决定(手势被识别),客户端都会收到TouchCancel事件的通知,以便他们可以相应地更新自己的状态。
pointCount()和point()函数可用于访问和迭代各个触摸点。
points()函数返回事件中包含的所有触摸点的列表。请注意,此列表可能为空,例如在TouchCancel事件的情况下。每个点都是QEventPoint类的一个实例。状态枚举描述了触摸点可能具有的不同状态。

事件交付和传播
默认情况下,QGuiApplication将QTouchEvent中的第一个触摸点转换为QMouseEvent。这使得在通常不处理QTouchEvent的现有小部件上启用触摸事件成为可能。有关执行此操作时需要注意的一些特殊事项的信息,请参见下文。
TouchBegin是发送到小部件的第一个触摸事件。TouchBegin事件包含一个特殊的接受标志,用于指示接收器是否想要该事件。默认情况下,该事件被接受。如果您的小部件没有处理触摸事件,您应该调用ignore()。TouchBegin事件沿父窗口小部件链向上传播,直到小部件用accept()接受它,或者事件过滤器使用它。对于QGraphicsItems,TouchBegin-事件传播到鼠标下的项目(类似于QGraphicsItem的鼠标事件传播)。

触点分组
如上所述,可能有几个小部件可以同时接收QTouchEvents。然而,Qt确保永远不会向同一个小部件发送重复的TouchBegin事件,例如,如果用户触摸了QGroupBox中的两个单独的小部件,并且两个小部件都忽略了TouchBegine事件,那么理论上在传播过程中可能会发生这种情况。
为了避免这种情况,Qt将使用以下规则将新的触摸点分组在一起:
- 当检测到第一个触摸点时,首先通过屏幕上的位置,其次通过传播规则来确定目的地小部件。
- 当检测到额外的触摸点时,Qt首先查看在新的触摸点下小部件的任何祖先或后代上是否有任何活动的触摸点。如果有,则将新触摸点与第一个分组,并且新触摸点将在单个QTouchEvent中发送到处理第一个触摸点的小部件。(新触摸点下的小部件将不会接收到事件)。
这使得兄弟窗口小部件可以独立处理触摸事件,同时确保QTouchEvents的顺序始终正确。

鼠标事件和触摸事件合成
QTouchEvent的交付独立于QMouseEvent的交付。应用程序标志AA_SsynthesizeTouchForUnhandledMouseEvents和AA_SynthesizeMouseForUnhandled TouseEvents可用于启用或禁用触摸事件到鼠标事件和鼠标事件到触摸事件的自动合成。

注意事项
如上所述,启用触摸事件意味着多个窗口小部件可以同时接收触摸事件。结合QTouchEvents的默认事件()处理,这为您设计触摸用户界面提供了极大的灵活性。注意其中的含义。例如,用户可能用一个手指移动QSlider,并用另一个手指按下QPushButton。这些窗口小部件发出的信号将被交错。
不支持使用QTouchEvent事件处理程序中的exec()方法之一(例如exec(或exec))递归到事件循环中。由于有多个事件接收者,递归可能会导致问题,包括但不限于丢失的事件和意外的无限递归。
QTouchEvents不受鼠标抓取或活动弹出窗口小部件的影响。当有多个活动触摸点时打开弹出窗口或抓住鼠标时,QTouchEvents的行为是未定义的。
QSinglePointEvent 包含单个点的指针事件(如鼠标事件)的基类。
QWheelEvent QWheelEvent类包含描述车轮事件的参数。
QTabletEvent QTabletEvent类包含描述Tablet事件的参数。
平板电脑事件由Wacom平板电脑和各种其他品牌的平板电脑外围设备以及某些类型的平板电脑附带的电磁手写笔设备生成。(它与触摸屏生成的QTouchEvent不同,即使在触摸屏上使用无源手写笔也是如此。)
平板电脑事件类似于鼠标事件;例如,x()、y()、pos()、globalX()、globalY()和globalPos()访问器提供光标位置,您可以看到按下了哪些按钮()(将手写笔尖端压在平板电脑表面相当于鼠标左键)。但平板电脑事件也会传递平板电脑设备驱动程序提供的一些额外信息;例如,您可能希望使用更高分辨率的坐标进行亚像素渲染(globalPosF()),根据工具对平板电脑表面的压力()调整颜色亮度,根据使用的工具类型使用不同的笔刷(deviceType()),根据工具相对于平板电脑表面的X轴和Y轴倾斜(xTilt()和yTilt())以某种方式调整画笔形状,如果用户切换到双端手写笔的另一端(pointerType()),则使用虚拟橡皮擦而不是画笔。
每个事件都包含一个接受标志,用于指示接收方是否想要该事件。如果您处理平板电脑事件,则应该调用accept();否则它将被发送到父窗口小部件。TabletInterProximity和TabletLeaveProximity事件除外:它们只发送到QApplication,不检查是否接受。
setEnabled()函数可用于启用或禁用小部件的鼠标、平板电脑和键盘事件。
事件处理程序tableEvent()接收TabletPress、TabletRlease和TabletMove事件。Qt将首先发送一个平板电脑事件,然后如果任何小部件都不接受它,它将发送一个鼠标事件。这允许非为平板电脑设计的应用程序的用户像使用鼠标一样使用平板电脑。然而,高分辨率绘图应用程序应该处理tablet事件,因为它们可能以更高的频率发生,这有利于平滑准确的绘图。如果平板电脑事件被拒绝,则合成鼠标事件可以被压缩以提高效率。
请注意,当手写笔悬停在平板电脑上时按下手写笔按钮将在某些类型的平板电脑上产生按钮按压,而在其他类型的平板计算机上,需要将手写笔按压在平板电脑表面上,以记录同时按下的手写笔按钮。

X11用户注意事项
如果平板电脑在xorg.conf中配置为使用Wacom驱动程序,则会有单独的XInput"设备"用于手写笔、橡皮擦以及(可选)光标和触摸板。Qt通过它们的名字来识别它们。否则,如果平板电脑配置为使用evdev驱动程序,则只有一个设备,应用程序可能无法区分手写笔和橡皮擦。

Windows用户注意事项
平板电脑支持当前需要安装WACOM窗口驱动程序,该驱动程序提供DLL wintab32.DLL。它包含在较旧的软件包中,例如pentablet_5.3.5-3.exe。
QNativeGestureEvent QNativeGestureEvent类包含描述手势事件的参数。
本机手势事件由操作系统生成,通常通过解释触控板触摸事件来生成。手势事件是高级事件,如缩放、旋转或平移。有几种类型持有增量值:也就是说,value()和delta()提供了上一个事件与当前事件之间的差异。

此外,BeginNativeGeture和EndNativeGesture在手势事件流之前和之后发送:
开始手势缩放手势缩放手势
事件流可能包括不同类型的交错手势:例如,两个手指捏手势会生成缩放和旋转事件流,PanNativeGesture有时可能会与这些事件交错,具体取决于平台。
其他类型是独立事件:每次检测到手势时,SmartZoomNativeGesture和SwipeNativeGeture只发生一次。
QMouseEvent QMouseEvent类包含描述鼠标事件的参数
当在小部件内按下或释放鼠标按钮,或者移动鼠标光标时,会发生鼠标事件。
只有在按下鼠标按钮时才会发生鼠标移动事件,除非使用setMouseTracking()启用了鼠标跟踪。
当在小部件内按下鼠标按钮时,Qt会自动抓取鼠标;小部件将继续接收鼠标事件,直到最后一个鼠标按钮被释放。
鼠标事件包含一个特殊的接受标志,用于指示接收器是否想要该事件。如果小部件没有处理鼠标事件,则应该调用ignore()。鼠标事件沿父窗口小部件链向上传播,直到小部件用accept()接受它,或者事件过滤器使用它。
键盘修饰键的状态可以通过调用从QInputEvent继承的modifiers()函数来找到。
position()函数给出了光标相对于接收鼠标事件的小部件或项目的位置。如果由于鼠标事件而移动小部件,请使用globalPosition()返回的全局位置来避免抖动。
setEnabled()函数可用于启用或禁用小部件的鼠标和键盘事件。
重新实现QWidget事件处理程序、mousePressEvent()、mouseReleaseEvent(),mouseDoubleClickEvent()和mouseMoveEvent()以在您自己的小部件中接收鼠标事件。
QHoverEvent QOverEvent类包含描述鼠标事件的参数
当鼠标光标移入、移出或移入小部件时,以及如果小部件具有WA_Hover属性,就会发生鼠标事件。
函数pos()给出当前光标的位置,而oldPos()则给出旧的鼠标位置。
HoverEnter和HoverLeave事件以及Enter和Leave事件之间有一些相似之处。然而,它们略有不同,因为我们在HoverEnter和HoverLeave的事件处理程序中执行update()。
悬停移动也与鼠标移动略有不同。让我们考虑一个包含子窗口B的顶级窗口a,该子窗口B又包含子窗口C(所有窗口都启用了鼠标跟踪):
88-事件与事件的处理函数-事件的类型与处理函数_第3张图片
现在,如果您将光标从A中间的顶部移动到底部,您将获得以下MouseMove事件:
A::MouseMove
B::MouseMove
C::MouseMove
您将获得与HoverMove相同的事件,只是无论是否接受该事件,该事件始终传播到顶层。它将仅使用WA_NoMousePropagation属性停止传播。
在这种情况下,事件将以以下方式发生:
A::HoverMove
A::HoverMove,B::HoverMove
A::HoverMove,B::HoverMove,C::HoverMove
QEnterEvent QEnterEvent类包含描述输入事件的参数
当鼠标光标进入窗口或小部件时,会发生Enter事件。
QKeyEvent QKeyEvent类描述了一个键事件。当按键被按下或释放时,按键事件被发送到具有键盘输入焦点的小部件。
密钥事件包含一个特殊的接受标志,该标志指示接收器是否将处理密钥事件。此标志默认为KeyPress和KeyRelease设置,因此在处理键事件时无需调用accept()。对于ShortcutOverride,接收器需要明确接受事件以触发覆盖。对键事件调用ignore()将把它传播到父窗口小部件。事件在父小部件链上向上传播,直到小部件接受它或事件过滤器使用它。
setEnabled()函数可用于启用或禁用小部件的鼠标和键盘事件。
事件处理程序keyPressEvent()、keyReleaseEvent(),keyPressEvent[()和keyReleaseEvent[(]接收关键事件。
QContextMenuEvent .QContextMenuEvent类包含描述上下文菜单事件的参数当用户执行与打开上下文菜单相关联的动作时,上下文菜单事件被发送到窗口小部件。打开上下文菜单所需的操作因平台而异;例如,在Windows上,按下菜单按钮或单击鼠标右键将导致发送此事件。
当此事件发生时,如果与上下文相关,则通常会显示带有上下文菜单的QMenu。
QIconDragEvent QIconDragEvent类表示主图标拖动已经开始。当窗口的主图标被拖走时,图标拖动事件会发送到窗口小部件。在macOS上,当窗口的代理图标从标题栏上拖下来时,就会发生这种情况。
开始使用拖放来响应此事件是正常的。
QHideEvent QHideEvent类提供了一个事件,该事件在小部件隐藏后发送。此事件在hide()返回之前发送,也在顶级窗口被用户隐藏(图标化)时发送。
如果自发性()为true,则该事件源自应用程序之外。在这种情况下,用户使用窗口管理器控件隐藏窗口,方法是将窗口图标化,或者切换到不可见窗口的另一个虚拟桌面。该窗口将被隐藏,但不会被收回。如果窗口被图标化,isMinimized()将返回true。
QHelpEvent QHelpEvent类提供了一个事件,用于请求有关小部件中特定点的有用信息。可以在应用程序中截获此事件,以便为自定义小部件提供工具提示或"这是什么?"帮助。类型()可以是工具提示或WhatsThis。
QFocusEvent QFocusEvent类包含小部件焦点事件的事件参数。当键盘输入焦点发生变化时,焦点事件会发送到窗口小部件。焦点事件是由于鼠标操作、按键(如Tab或Backtab)、窗口系统、弹出菜单、键盘快捷键或其他特定于应用程序的原因而发生的。特定焦点事件的原因由reason()在相应的事件处理程序中返回。
事件处理程序focusInEvent()、focusOutEvent(),focusInEvent和focusOutEvent()接收焦点事件。
QFileOpenEvent QFileOpenEvent类提供了一个事件,当有打开文件或URL的请求时将发送该事件。
当操作系统请求打开文件或URL时,文件打开事件将发送到instance()。这是一个高级事件,可能由不同的用户操作引起,具体取决于用户的桌面环境;例如,双击macOS上Finder中的文件图标。
此事件仅用于向应用程序通知请求。可以安全地忽略它。
macOS示例
为了在macOS上触发事件,必须将应用程序配置为让操作系统知道它应该对什么类型的文件做出反应。
例如,以下Info.plist文件声明应用程序可以作为具有PNG扩展名的文件的查看器:




CFBundleDocumentTypes


CFBundleTypeExtensions

png

CFBundleTypeRole
Viewer




以下QApplication子类的实现打印文件的路径,例如,该文件被放置在应用程序的Dock图标上。
from PySide6.QtWidgets import QApplication

from PySide6.QtGui import QFileOpenEvent
from PySide6.QtWidgets import QPushButton
class MyApplication(QApplication):

# public
MyApplication(int argc,char **argv)
super().init(argc,argv)


event = bool(QEvent event)

if event.type()== QEvent.FileOpen:
openEvent = QFileOpenEvent(event)
print(“Open file”,openEvent.file())

return QApplication.event(event)
QExposeEvent QExposeEvent类包含用于公开事件的事件参数。
当暴露事件在未暴露和暴露状态之间移动时,它们会被发送到窗口。
暴露的窗口可能对用户可见。如果窗口被移出屏幕、被另一个窗口完全遮挡、最小化或类似情况,则会向该窗口发送一个暴露事件,isExposed()可能会更改为false。
暴露事件不应用于绘制。改为处理QPaintEvent。
事件处理程序exposeEvent()接收公开事件。
QDropEvent QDropEvent类提供了一个在拖放操作完成时发送的事件。
当小部件接受丢弃事件时,如果它接受了发送给它的最新QDragEnterEvent或QDragMoveEvent,它将接收此事件。
drop事件包含一个提议的操作,可从proposedAction()获得,供小部件接受或忽略。如果该操作可以由小部件处理,那么应该调用acceptProposedAction()函数。由于提议的动作可以是DropAction值的组合,因此选择这些值中的一个作为默认动作或要求用户选择他们的首选动作可能是有用的。
如果建议的删除操作不合适,可能是因为您的自定义小部件不支持该操作,您可以通过使用首选操作调用setDropAction(),将其替换为任何可能的删除操作。如果您设置的值不存在于possibleActions()返回的值的按位OR组合中,则将使用默认的复制操作。一旦设置了替换删除操作,请调用accept()而不是acceptProposedAction()来完成删除操作。
mimeData()函数在QMimeData对象中提供小部件上丢弃的数据。除了数据本身之外,它还包含有关数据的MIME类型的信息。
QDragMoveEvent QDragMoveEvent类提供了一个在进行拖放操作时发送的事件。
如果小部件接受拖放事件和输入事件,则当拖动在其边界内时,它将重复接收拖放事件。小部件应该检查事件,看看它提供了什么样的数据,并在适当的时候调用accept()函数来接受丢弃。
answerRect()函数提供的矩形可用于限制小部件的某些部分的删除。例如,我们可以检查矩形是否与某个子窗口小部件的几何体相交,如果是这样的话,只调用acceptProposedAction()。
请注意,这个类从QDropEvent继承了它的大部分功能。
QDragEnterEvent QDragEnterEvent类提供了一个事件,当拖放操作进入小部件时,该事件会被发送到小部件。
小部件必须接受此事件,才能接收在进行拖放操作时发送的拖放事件。拖动输入事件之后总是紧跟着拖动移动事件。
QDragEnterEvent从QDragMoveEvent继承了其大部分功能,而QDragMoveEvents又从QDropEvent继承了大部分功能。
QDragLeaveEvent QDragLeaveEvent类提供了一个事件,当拖放操作离开小部件时,该事件会被发送到小部件。
此事件之前总是一个QDragEnterEvent和一系列QDragMoveEvent。如果改为发送QDropEvent,则不发送该事件。
QCloseEvent QCloseEvent类包含描述关闭事件的参数。
关闭事件被发送到用户想要关闭的窗口小部件,通常通过从窗口菜单中选择"关闭",或单击X标题栏按钮。当您调用close()以编程方式关闭小部件时,也会发送它们。
关闭事件包含一个标志,指示接收器是否希望关闭小部件。当小部件接受关闭事件时,它将被隐藏(如果它是使用WA_DeleteClose标志创建的,则会被销毁)。如果它拒绝接受关闭事件,则不会发生任何事情。(在X11下,窗口管理器可能会强制关闭窗口;但在撰写本文时,我们还不知道有任何窗口管理器会这样做。)
事件处理程序closeEvent()接收关闭事件。此事件处理程序的默认实现接受关闭事件。如果您不希望您的小部件被隐藏,或者想要一些特殊的处理,您应该重新实现事件处理程序并忽略()事件。
Application示例中的closeEvent()显示了一个关闭事件处理程序,该处理程序询问是否在关闭前保存文档。
如果希望小部件在关闭时被删除,请使用WA_DeleteClose标志创建它。这对于多窗口应用程序中的独立顶层窗口非常有用。
QObjects在被删除时会发出destroyed()信号。
如果最后一个顶级窗口关闭,则会发出lastWindowClosed()信号。
如果事件的接收者已同意关闭小部件,则isAccepted()函数返回true;调用accept()以同意关闭小部件,如果此事件的接收者不希望关闭小部件则调用ignore()。
QActionEvent QActionEvent类提供在添加、删除或更改QAction时生成的事件。
可以将操作添加到控件中,例如使用addAction()。这会生成一个ActionAdded事件,您可以处理该事件以提供自定义行为。例如,QToolBar重新实现actionEvent()来为操作创建QToolButton。
QTimerEvent QTimerEvent类包含描述计时器事件的参数。
计时器事件以规则的间隔发送到已启动一个或多个计时器的对象。每个定时器都有一个唯一的标识符。计时器是用startTimer()启动的。
QTimer类提供了一个高级编程接口,该接口使用信号而不是事件。它还提供单次定时器。
事件处理程序timerEvent()接收计时器事件。
QDynamicPropertyChangeEvent QDynamicPropertyChangeEvent类包含动态属性更改事件的事件参数。
当使用setProperty()动态添加、更改或删除属性时,将向对象发送动态属性更改事件。
QChildEvent QChildEvent类包含子对象事件的事件参数。
添加或删除子对象时,会立即将子事件发送到对象。
在这两种情况下,您只能依赖于子对象是QObject(或者,如果isWidgetType()返回true,则依赖于QWidget)。这是因为在ChildAdded的情况下,孩子还没有完全构建;在ChildRemoved的情况下,它可能已经被销毁。
这些事件的处理程序是childEvent()。

event()函数

当GUI应用程序捕捉到事件发生后,会首先将其发送到 QWidget 或子类的event(QEvent)函数中进行数据处理,如果没有重写event()函数进行事件处,理事件将会分发到事件默认的处理函数中,因此event()函数是事件的集散地。

如果重写了 event()函数当event()函数的返回值是True 时,表示事件已经处理完毕事件不会再发送给其他处理函数;当event()函数的返回值是 False时,表示事件还没有处理完毕。event()函数可以截获某些类型的事件,并处理事件

下面的程序是将上节中的例子做了改动将鼠标的单击事件放到event()函数中进行处理,只截获QEvent.MouseButtonPress事件,通过 super()函数调用父类的 event()函数其他类型的事件仍交由QWidget 的event()函数处理和分发。

# -*- coding: UTF-8 -*-
# File date: Hi_2023/3/1 21:18
# File_name: 02-event()函数.py
import sys
from PySide6.QtWidgets import QApplication,QWidget,QLineEdit
from PySide6.QtCore import QEvent,Qt


class MyWindow(QWidget):
    def __init__(self,parent=None):
        super().__init__(parent)
        self.resize(500,500)
        self.lineEdit = QLineEdit(self)
        self.lineEdit.setGeometry(0,0,500,30)

    def event(self,even):  # 重写event函数
        if even.type()== QEvent.MouseButtonPress:  # 按键的情况
            template1 ="单击点的窗口坐标是x:{} y:{}"
            template2 ="单击点的屏幕坐标是x:{} y:{}"

            if even.button()== Qt.LeftButton:  # button()获取键或右键
                string = template1.format(even.position().x(),even.position().y())# x()和()获取窗口坐标
                self.lineEdit.setText(string)
                return True

            elif even.button()== Qt.RightButton:  # globalX()和globalY()获取全局坐标
                string = template2.format(even.globalPosition().x(),even.globalPosition().y())
                self.lineEdit.setText(string)
                return True

            else:  # 按中键的情况
                return True

        else:  # 对于不是按鼠标键的事件,交给 owidget 来处理
            finished = super().event(even)# super()函数调用父类丽数
            return finished


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = MyWindow()

    win.show()
    sys.exit(app.exec())

事件处理和过滤的方法

PySide/PyQt 提供了如下 5 种事件处理和过滤的方法(由弱到强),其中前两种方法使用得比较频繁。在一般情况下,应尽量避免使用第 3~5 种方法,因为使用这3 种方法不仅会增加代码的复杂性,还会降低程序性能。

  • 重新实现事件函数
    mousePressEvent()、keyPressEvent()和 paintEvent()是常规的事件处理方法

  • 重新实现 QObject.event()函数
    该方法一般用在 PySide/PyQt 没有提供事件处理函数的情况下,使用这种方法可以新增事件。

  • 安装事件过滤器
    如果对 QObject 调用 installEventFilter,则相当于为这个 QObject 安装了一个事件过滤器。

    QObject 的全部事件都会先传递到事件过滤函数eventFilter()中,在这个函数中可以抛弃或修改这些事件,如可以对自已感兴趣的事件使用自定义的事件处理机制,对其他事件使用默认的事件处理机制。

    由于这种方法会对调用 installEventFilter 的所有 QObject的事件进行过滤,因此如果要过滤的事件比较多,就会降低程序的性能。

  • 在QApplication 中安装事件过滤器
    这种方法比上一种方法更强大

    QApplication 的事件过滤器将捕获 QObject 的全部事件,并且先获得该事件。

    也就是说,在将事件发送给其他任何一个事件过滤器之前(就是在第 3 种方法之前),都会先发送给 QApplication 的事件过滤器。

  • 重新实现QApplication的 notify0函数
    PySide/PyQt使用notify0函数来分发事件。要想在任何事件处理器之前捕获事件,唯的方法就是重新实现 QApplication 的 notify0函数。在实践中,只有调试时才会使用这种方法。

重新实现事件函数和重载 event()函数例子

这个例子比较经典,涉及提到的前两种方法,并且内容很丰富,基本上包含对事件处理的绝大部分需求

# -*- coding: UTF-8 -*-
# File date: Hi_2023/3/1 23:00
# File_name: demo.py


import sys
from PySide6.QtCore import(QEvent,QTimer,Qt)
from PySide6.QtWidgets import(QApplication,QMenu,QWidget)
from PySide6.QtGui import QPainter


class Widget(QWidget):
    def __init__(self,parent=None):
        super(Widget,self).__init__(parent)
        self.justDoubleClicked = False
        self.key =""
        self.text =""
        self.message =""
        self.resize(400,300)
        self.move(100,100)
        self.setWindowTitle("Events")
        QTimer.singleShot(0,self.giveHelp)# 避免窗口大小重绘事件的影响,可以把参数0改变成3000(3秒),然后在运行,就可以明白这行代码的意思。

    def giveHelp(self):
        self.text ="请点击这里触发追踪鼠标功能"
        self.update()# 重绘事件,也就是触发paintEvent函数。

    # 重新实现关闭事件
    def closeEvent(self,event):
        print("Closed")

    # 重新实现上下文菜单事件
    def contextMenuEvent(self,event):
        menu = QMenu(self)
        oneAction = menu.addAction("&One")
        twoAction = menu.addAction("&Two")
        oneAction.triggered.connect(self.one)
        twoAction.triggered.connect(self.two)
        if not self.message:
            menu.addSeparator()
            threeAction = menu.addAction("Thre&e")
            threeAction.triggered.connect(self.three)
        menu.exec(event.globalPos())

    # 上下文菜单槽函数
    def one(self):
        self.message ="Menu option One"
        self.update()

    def two(self):
        self.message ="Menu option Two"
        self.update()

    def three(self):
        self.message ="Menu option Three"
        self.update()

    # 重新实现绘制事件
    def paintEvent(self,event):
        text = self.text
        i = text.find("\n\n")
        if i >= 0:
            text = text[0:i]
        if self.key:  # 若触发了键盘按钮,则在文本信息中记录这个按钮信息。
            text +="\n\n你按下了: {0}".format(self.key)
        painter = QPainter(self)
        painter.setRenderHint(QPainter.TextAntialiasing)
        painter.drawText(self.rect(),Qt.AlignCenter,text)# 绘制信息文本的内容
        if self.message:  # 若消息文本存在则在底部居中绘制消息,5秒钟后清空消息文本并重绘。
            painter.drawText(self.rect(),Qt.AlignBottom | Qt.AlignHCenter,
                             self.message)
            QTimer.singleShot(5000,self.clearMessage)
            QTimer.singleShot(5000,self.update)

    # 清空消息文本的槽函数
    def clearMessage(self):
        self.message =""

    # 重新实现调整窗口大小事件
    def resizeEvent(self,event):
        self.text ="调整窗口大小为: QSize({0},{1})".format(
            event.size().width(),event.size().height())
        self.update()

    # 重新实现鼠标释放事件
    def mouseReleaseEvent(self,event):
        # 若鼠标释放为双击释放,则不跟踪鼠标移动
        # 若鼠标释放为单击释放,则需要改变跟踪功能的状态,如果开启跟踪功能的话就跟踪,不开启跟踪功能就不跟踪
        if self.justDoubleClicked:
            self.justDoubleClicked = False
        else:
            self.setMouseTracking(not self.hasMouseTracking())# 单击鼠标
            if self.hasMouseTracking():
                self.text ="开启鼠标跟踪功能.\n"+ \
"请移动一下鼠标!\n"+ \
"单击鼠标可以关闭这个功能"
            else:
                self.text ="关闭鼠标跟踪功能.\n"+ \
"单击鼠标可以开启这个功能"
            self.update()

    # 重新实现鼠标移动事件
    def mouseMoveEvent(self,event):
        if not self.justDoubleClicked:
            globalPos = self.mapToGlobal(event.position())# 窗口坐标转换为屏幕坐标
            self.text =	f"鼠标位置: 窗口坐标为:QPoint({0},{1})屏幕坐标为:QPoint({2},{3})".format(event.position().x(),event.position().y(),globalPos.x(),globalPos.y())
            self.update()

    # 重新实现鼠标双击事件
    def mouseDoubleClickEvent(self,event):
        self.justDoubleClicked = True
        self.text ="你双击了鼠标"
        self.update()

    # 重新实现键盘按下事件
    def keyPressEvent(self,event):
        self.key =""
        if event.key()== Qt.Key_Home:
            self.key ="Home"
        elif event.key()== Qt.Key_End:
            self.key ="End"
        elif event.key()== Qt.Key_PageUp:
            if event.modifiers()& Qt.ControlModifier:
                self.key ="Ctrl+PageUp"
            else:
                self.key ="PageUp"
        elif event.key()== Qt.Key_PageDown:
            if event.modifiers()& Qt.ControlModifier:
                self.key ="Ctrl+PageDown"
            else:
                self.key ="PageDown"
        elif Qt.Key_A <= event.key()<= Qt.Key_Z:
            if event.modifiers()& Qt.ShiftModifier:
                self.key ="Shift+"
            self.key += event.text()
        if self.key:
            self.key = self.key
            self.update()
        else:
            QWidget.keyPressEvent(self,event)

    # 重新实现其他事件,适用于PyQt没有提供该事件的处理函数的情况,Tab键由于涉及焦点切换,不会传递给keyPressEvent,因此,需要在这里重新定义。
    def event(self,event):
        if(event.type()== QEvent.KeyPress and
                event.key()== Qt.Key_Tab):
            self.key ="在event()中捕获Tab键"
            self.update()
            return True
        return QWidget.event(self,event)


if __name__ =="__main__":
    app = QApplication(sys.argv)
    form = Widget()
    form.show()
    app.exec()

重新实现事件函数

下面对本案例的几个关键点进行说明。

  • 一是类的建立。

    创建text和message 两个变量,使用paintEvent()函数把它们输出到窗口中。

    update()函数的作用是更新窗口。由于在窗口更新过程中会触发一次 paintEvent()函数. paintEvent()是窗口基类QWidget 的内部函数因此在本案例中update()函数的作用等同于paintEvent()函数的作用。代码如下:

    class Widget(QWidget):
        def __init__(self,parent=None):
            super(Widget,self).__init__(parent)
            self.justDoubleClicked = False
            self.key =""
            self.text =""
            self.message =""
            self.resize(400,300)
            self.move(100,100)
            self.setWindowTitle("Events")
            QTimer.singleShot(0,self.giveHelp)# 避免窗口大小重绘事件的影响,可以把参数0改变成3000(3秒),然后在运行,就可以明白这行代码的意思。
            
    	    def giveHelp(self):
                self.text ="请点击这里触发追踪鼠标功能"
                self.update()# 重绘事件,也就是触发paintEvent函数。
    
  • 二是重新实现窗口关闭事件与上下文菜单事件

    • 上下文菜单事件主要影响 message变量的结果,paintEvent()函数负责把这个变量在窗口底部输出。代码如下:

      # 重新实现关闭事件
      def closeEvent(self,event):
          print("Closed")
      
      # 重新实现上下文菜单事件
      def contextMenuEvent(self,event):
          menu = QMenu(self)
          oneAction = menu.addAction("&One")
          twoAction = menu.addAction("&Two")
          oneAction.triggered.connect(self.one)
          twoAction.triggered.connect(self.two)
          if not self.message:
              menu.addSeparator()
              threeAction = menu.addAction("Thre&e")
              threeAction.triggered.connect(self.three)
          menu.exec(event.globalPos())
      
      # 上下文菜单槽函数
      def one(self):
          self.message ="Menu option One"
          self.update()
      
      def two(self):
          self.message ="Menu option Two"
          self.update()
      
      def three(self):
          self.message ="Menu option Three"
          self.update()
      
    • 绘制事件是代码的核心事件,它的主要作用是时刻跟踪 text 与 message 这两个变量并把 text 变量的内容绘制到窗口的中部,把 message 变量的内容绘制到窗口的底部(保持 5秒后就会被清空)。代码如下:

      # 重新实现绘制事件
      def paintEvent(self,event):
          text = self.text
          i = text.find("\n\n")
          if i >= 0:
              text = text[0:i]
          if self.key:  # 若触发了键盘按钮,则在文本信息中记录这个按钮信息。
              text +="\n\n你按下了: {0}".format(self.key)
          painter = QPainter(self)
          painter.setRenderHint(QPainter.TextAntialiasing)
          painter.drawText(self.rect(),Qt.AlignCenter,text)# 绘制信息文本的内容
          if self.message:  # 若消息文本存在则在底部居中绘制消息,5秒钟后清空消息文本并重绘。
              painter.drawText(self.rect(),Qt.AlignBottom | Qt.AlignHCenter,self.message)
              QTimer.singleShot(5000,self.clearMessage)
              QTimer.singleShot(5000,self.update)
      
      # 清空消息文本的槽函数
      def clearMessage(self):
          self.message =""
      
  • 三是重新实现调整窗口大小事件,代码如下:

    # 重新实现调整窗口大小事件
    def resizeEvent(self,event):
        self.text ="调整窗口大小为: QSize({0},{1})".format(
            event.size().width(),event.size().height())
        self.update()
    
    • 重新实现鼠标释放事件。若为双击释放,则不跟踪鼠标移动;若为单击释放,则需要改变跟踪功能的状态,如果开启跟踪功能就跟踪,否则不跟踪。代码如下:

      # 重新实现鼠标释放事件
      def mouseReleaseEvent(self,event):
          # 若鼠标释放为双击释放,则不跟踪鼠标移动
          # 若鼠标释放为单击释放,则需要改变跟踪功能的状态,如果开启跟踪功能的话就跟踪,不开启跟踪功能就不跟踪
          if self.justDoubleClicked:
              self.justDoubleClicked = False
          else:
              self.setMouseTracking(not self.hasMouseTracking())# 单击鼠标
              if self.hasMouseTracking():
                  self.text ="开启鼠标跟踪功能.\n"+ \
      "请移动一下鼠标!\n"+ \
      "单击鼠标可以关闭这个功能"
              else:
                  self.text ="关闭鼠标跟踪功能.\n"+ \
      "单击鼠标可以开启这个功能"
              self.update()
      
    • 重新实现鼠标移动事件与鼠标双击事件,代码如下

      # 重新实现鼠标移动事件
      def mouseMoveEvent(self,event):
          if not self.justDoubleClicked:
              globalPos = self.mapToGlobal(event.position())# 窗口坐标转换为屏幕坐标
              self.text = f"鼠标位置: 窗口坐标为:QPoint({0},{1})屏幕坐标为:QPoint({2},{3})".format(event.position().x(),event.position().y(),globalPos.x(),globalPos.y())
              self.update()
      
      # 重新实现鼠标双击事件
      def mouseDoubleClickEvent(self,event):
          self.justDoubleClicked = True
          self.text ="你双击了鼠标"
          self.update()
      
    • 重新实现键盘按下事件,代码如下

      # 重新实现键盘按下事件
      def keyPressEvent(self,event):
          self.key =""
          if event.key()== Qt.Key_Home:
              self.key ="Home"
          elif event.key()== Qt.Key_End:
              self.key ="End"
          elif event.key()== Qt.Key_PageUp:
              if event.modifiers()& Qt.ControlModifier:
                  self.key ="Ctrl+PageUp"
              else:
                  self.key ="PageUp"
          elif event.key()== Qt.Key_PageDown:
              if event.modifiers()& Qt.ControlModifier:
                  self.key ="Ctrl+PageDown"
              else:
                  self.key ="PageDown"
          elif Qt.Key_A <= event.key()<= Qt.Key_Z:
              if event.modifiers()& Qt.ShiftModifier:
                  self.key ="Shift+"
              self.key += event.text()
          if self.key:
              self.key = self.key
              self.update()
          else:
              QWidget.keyPressEvent(self,event)
      
重载 event()函数

第2种事件处理方法是重载 event()函数。对于窗口来说,所有的事件都会传递给Event()函数,该函数会根据事件的类型把事件分配给不同的函数进行处理。

例如,绘图事件会交给paintEvent()函数处理,鼠标移动事件会交给mouseMoveEvent()函数处理,键盘按下事件会交给keyPressEvent()函数处理有一种特殊情况是对Tab键的触发行为Event()函数对 Tab 键的处理机制是把焦点从当前窗口控件的位置切换到 Tab 键次序中下一个窗口控件的位置,并返回 True,而不是交给 keyPressEvent()函数处理。

因此,这里需要在event()函数中重新改写按下 Tab 键的处理逻辑,使它与键盘上普通的键没有什么不同。代码如下:

# 重新实现其他事件,适用于PyQt没有提供该事件的处理函数的情况,Tab键由于涉及焦点切换,不会传递给keyPressEvent,因此,需要在这里重新定义。
def event(self,event):
    if(event.type()== QEvent.KeyPress and
            event.key()== Qt.Key_Tab):
        self.key ="在event()中捕获Tab键"
        self.update()
        return True
    return QWidget.event(self,event)
安装事件过滤器

安装事件过滤器例子

# -*- coding: utf-8 -*-
from PySide6.QtGui import *
from PySide6.QtCore import *
from PySide6.QtWidgets import *
import sys
import os
os.chdir(os.path.dirname(__file__))

class EventFilter(QDialog):
    def __init__(self,parent=None):
        super(EventFilter,self).__init__(parent)
        self.setWindowTitle("事件过滤器")

        self.label1 = QLabel("请点击")
        self.label2 = QLabel("请点击")
        self.label3 = QLabel("请点击")
        self.LabelState = QLabel("test")

        self.image1 = QImage("images/cartoon1.ico")
        self.image2 = QImage("images/cartoon1.ico")
        self.image3 = QImage("images/cartoon1.ico")

        self.width = 600
        self.height = 300

        self.resize(self.width,self.height)

        self.label1.installEventFilter(self)
        self.label2.installEventFilter(self)
        self.label3.installEventFilter(self)

        mainLayout = QGridLayout(self)
        mainLayout.addWidget(self.label1,500,0)
        mainLayout.addWidget(self.label2,500,1)
        mainLayout.addWidget(self.label3,500,2)
        mainLayout.addWidget(self.LabelState,600,1)
        self.setLayout(mainLayout)

    def eventFilter(self,watched,event):
        if watched == self.label1:  # 只对label1的点击事件进行过滤,重写其行为,其他的事件会被忽略
            if event.type()== QEvent.MouseButtonPress:  # 这里对鼠标按下事件进行过滤,重写其行为
                mouseEvent = QMouseEvent(event)
                if mouseEvent.buttons()== Qt.LeftButton:
                    self.LabelState.setText("按下鼠标左键")
                elif mouseEvent.buttons()== Qt.MiddleButton:
                    self.LabelState.setText("按下鼠标中间键")
                elif mouseEvent.buttons()== Qt.RightButton:
                    self.LabelState.setText("按下鼠标右键")

                '''转换图片大小'''
                transform = QTransform()
                transform.scale(0.5,0.5)
                tmp = self.image1.transformed(transform)
                self.label1.setPixmap(QPixmap.fromImage(tmp))
            if event.type()== QEvent.MouseButtonRelease:  # 这里对鼠标释放事件进行过滤,重写其行为
                self.LabelState.setText("释放鼠标按钮")
                self.label1.setPixmap(QPixmap.fromImage(self.image1))
        return QDialog.eventFilter(self,watched,event)# 其他情况会返回系统默认的事件处理方法。


if __name__ == '__main__':
    app = QApplication(sys.argv)
    dialog = EventFilter()
    dialog.show()
    app.exec()

如果使用事件过滤器,那么关键是做好两步。

  • 对要过滤的控件设置installEventFilter,这些控件的所有事件都会被eventFilter0函数接收并处理。

    installEventFilter 的使用方法如下:

    self.label1.installEventFilter(self)
    self.label2.installEventFilter(self)
    self.label3.installEventFilter(self)
    
  • 在 eventFilter()函数中处理这些控件的事件信息。

    下面的代码表示这个过滤器只对 label1 的事件进行处理,并且只处理它的鼠标按下事件(MouseButtonPress)和鼠标释放事件(MouseButtonRelease):

    def eventFilter(self,watched,event):
        if watched == self.label1:  # 只对label1的点击事件进行过滤,重写其行为,其他的事件会被忽略
            if event.type()== QEvent.MouseButtonPress:  # 这里对鼠标按下事件进行过滤,重写其行为
                mouseEvent = QMouseEvent(event)
                if mouseEvent.buttons()== Qt.LeftButton:
                    self.LabelState.setText("按下鼠标左键")
                elif mouseEvent.buttons()== Qt.MiddleButton:
                    self.LabelState.setText("按下鼠标中间键")
                elif mouseEvent.buttons()== Qt.RightButton:
                    self.LabelState.setText("按下鼠标右键")
    
                '''转换图片大小'''
                transform = QTransform()
                transform.scale(0.5,0.5)
                tmp = self.image1.transformed(transform)
                self.label1.setPixmap(QPixmap.fromImage(tmp))
            if event.type()== QEvent.MouseButtonRelease:  # 这里对鼠标释放事件进行过滤,重写其行为
                self.LabelState.setText("释放鼠标按钮")
                self.label1.setPixmap(QPixmap.fromImage(self.image1))
        return QDialog.eventFilter(self,watched,event)# 其他情况会返回系统默认的事件处理方法。
    

    需要注意如下4行代码:

    '''转换图片大小'''
    transform = QTransform()
    transform.scale(0.5,0.5)
    tmp = self.image1.transformed(transform)
    self.label1.setPixmap(QPixmap.fromImage(tmp))
    

    这4行代码表示如果按下鼠标按键,就会对 label1 装载的图片进行缩放(长和宽各缩放为原来的一半)。

在 QApplication 中安装事件过滤器

QApplication 中安装事件过滤器例子

# -*- coding: utf-8 -*-
from PySide6.QtGui import *
from PySide6.QtCore import *
from PySide6.QtWidgets import *
import sys
import os

os.chdir(os.path.dirname(__file__))


class EventFilter(QDialog):
    def __init__(self,parent=None):
        super(EventFilter,self).__init__(parent)
        self.setWindowTitle("事件过滤器")

        self.label1 = QLabel("请点击")
        self.label2 = QLabel("请点击")
        self.label3 = QLabel("请点击")
        self.LabelState = QLabel("test")

        self.image1 = QImage("images/cartoon1.ico")
        self.image2 = QImage("images/cartoon1.ico")
        self.image3 = QImage("images/cartoon1.ico")

        self.width = 600
        self.height = 300

        self.resize(self.width,self.height)

        # self.label1.installEventFilter(self)
        # self.label2.installEventFilter(self)
        # self.label3.installEventFilter(self)

        mainLayout = QGridLayout(self)
        mainLayout.addWidget(self.label1,500,0)
        mainLayout.addWidget(self.label2,500,1)
        mainLayout.addWidget(self.label3,500,2)
        mainLayout.addWidget(self.LabelState,600,1)
        self.setLayout(mainLayout)

    def eventFilter(self,watched,event):
        print(type(watched))
        if watched == self.label1:  # 只对label1的点击事件进行过滤,重写其行为,其他的事件会被忽略
            if event.type()== QEvent.MouseButtonPress:  # 这里对鼠标按下事件进行过滤,重写其行为
                mouseEvent = QMouseEvent(event)
                if mouseEvent.buttons()== Qt.LeftButton:
                    self.LabelState.setText("按下鼠标左键")
                elif mouseEvent.buttons()== Qt.MidButton:
                    self.LabelState.setText("按下鼠标中间键")
                elif mouseEvent.buttons()== Qt.RightButton:
                    self.LabelState.setText("按下鼠标右键")

                '''转换图片大小'''
                transform = QTransform()
                transform.scale(0.5,0.5)
                tmp = self.image1.transformed(transform)
                self.label1.setPixmap(QPixmap.fromImage(tmp))
            if event.type()== QEvent.MouseButtonRelease:  # 这里对鼠标释放事件进行过滤,重写其行为
                self.LabelState.setText("释放鼠标按钮")
                self.label1.setPixmap(QPixmap.fromImage(self.image1))
        return QDialog.eventFilter(self,watched,event)# 其他情况会返回系统默认的事件处理方法。


if __name__ == '__main__':
    app = QApplication(sys.argv)
    dialog = EventFilter()
    app.installEventFilter(dialog)
    dialog.show()
    app.exec()

第4种事件处理方法(在 QApplication 中安装事件过滤器)的使用也非常简单,与第 3 种事件处理方法相比,只需要简单地修改两处代码即可。

屏蔽3个label 标签控件的 installEventFilter 的代码

# self.label1.installEventFilter(self)
# self.label2.installEventFilter(self)
# self.label3.installEventFilter(self)

对于在 QApplication 中安装 installEventFilter,下面的代码表示 dialog 的所有事件都要经过 EventFilter()函数的处理,而不仅仅是3个标签控件的事件:

if __name__ == '__main__':
    app = QApplication(sys.argv)
    dialog = EventFilter()
    app.installEventFilter(dialog)
    dialog.show()
    app.exec()

为了更好地展示第4种方法与第3种方法的区别,这里在eventFilter0函数中添加了如下代码:

def eventFilter(self,watched,event):
    print(type(watched))
    
"""输出如下













...











"""
重写QApplication 的 notify()函数

提到的第5种方法(重写QApplication 的 notify()函数)在实际中基本上用不到,所以这里不再介绍。

你可能感兴趣的:(#,pyside6,Python,GUI,开发语言,qt,python,音视频,媒体,网络)