详解PyQt5 事件处理机制

作者:SongYuLong的博客 时间:2023-04-06 00:09:34 

PyQt5 事件处理机制

PyQt为事件处理提供了两种机制:高级的信号与槽机制,以及低级的事件处理机制。信号与槽可以说是对事件处理机制的高级封装。
常见事件类型:

  • 键盘事件:按键按下和松开。

  • 鼠标事件:鼠标指针移动,鼠标按下和松开。

  • 拖放事件:用鼠标进行拖放。

  • 滚轮事件:鼠标滚轮滚动。

  • 绘屏事件:重绘屏幕的某些部分。

  • 定时事件:定时器到时。

  • 焦点事件:键盘焦点移动。

  • 进入/离开事件:鼠标指针移入Widget内,或者移出。

  • 移动事件:Widget的位置改变。

  • 大小改变事件:Widget的大小改变。

  • 显示/隐藏事件:Widget显示和隐藏。

  • 窗口事件:窗口是否为当前窗口。

PyQt提供了如下5种事件处理和过滤方法(有弱到强):

  • 重新实现事件函数,比如mousePressEvent(),keyPressEvent()等等。

  • 重新实现QObject.event()。

  • 安装时间过滤器。

  • 在QApplication中安装事件过滤器。

  • 重新实现QAppliction的notifiy()方法。

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

class MyEventDemoWindow(QWidget):
   def __init__(self, parent=None):
       super(MyEventDemoWindow, self).__init__(parent)
       self.justDoubleClikcked = False
       self.key = ""
       self.text = ""
       self.message = ""
       self.resize(400, 300)
       self.move(100, 100)
       self.setWindowTitle("Events Demo 1")
       QTimer.singleShot(1000, self.giveHelp)

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("&Three")
           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:
           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) -> None:
       if self.justDoubleClikcked:
           self.justDoubleClikcked = False
       else :
           self.setMouseTracking(not self.hasMouseTracking()) # 单击鼠标
           if self.hasMouseTracking():
               self.text = "你释放了鼠标 开启鼠标跟踪功能.\n\n" + \
                       "请移动鼠标\n\n" + \
                       "单击鼠标可以关闭这个功能"
           else:
               self.text = "你释放了鼠标  关闭鼠标跟踪功能" + \
                       "单击鼠标可以开启这个功能"
       self.update()

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

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

def mousePressEvent(self, event):
       self.text = "你按下了鼠标"
       self.update()

def keyPressEvent(self, event):
       self.text = "你按下了按键"
       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 + Page Up"
           else:
               self.key = "Page Up"
       elif event.key() == Qt.Key_PageDown:
           if event.modifiers() & Qt.ControlModifier:
               self.key = "Ctrl + Key_PageDown"
           else:
               self.key = "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)

def keyReleaseEvent(self, event):
       self.text = "你释放了按键"
       self.update()

'''重新实现event,捕获Tab键'''
   def event(self, event):
       if (event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab):
           self.key = "在event() 中捕获Tab键"
           self.update()
           return True # 返回True表示本次事件已经执行处理
       else:
           return QWidget.event(self, event) # 继续处理事件

if __name__ == "__main__":
   app = QApplication(sys.argv)
   win = MyEventDemoWindow()
   win.show()
   sys.exit(app.exec_())

详解PyQt5 事件处理机制

import sys
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

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("pyqt5/images/cartoon1.ico")
       self.image2 = QImage("pyqt5/images/cartoon1.ico")
       self.image3 = QImage("pyqt5/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)
   win = EventFilter()
   win.show()
   app.exec_()

详解PyQt5 事件处理机制

来源:https://blog.csdn.net/songyulong8888/article/details/128104547

标签:PyQt5,事件,机制
0
投稿

猜你喜欢

  • ACCESS中Field对象的标题属性

    2008-11-20 17:44:00
  • 浅谈MySQL timestamp(3)问题

    2024-01-14 17:47:23
  • Python动态演示旋转矩阵的作用详解

    2022-08-21 02:35:15
  • css表单中textarea域背景图片设置方法

    2008-04-21 13:56:00
  • Python中OpenCV Tutorials 20  高动态范围成像的实现步骤

    2022-04-02 07:24:20
  • js版sliderBar(滑动条)控件

    2008-10-18 15:59:00
  • OBJECTPROPERTY与sp_rename更改对象名称的介绍

    2012-01-29 18:04:39
  • python进度条库tqdm的基本操作方法

    2021-03-02 08:31:22
  • go MethodByName()不能获取私有方法的解决

    2024-04-30 10:07:35
  • mac 安装python网络请求包requests方法

    2023-08-05 09:01:41
  • ASP面向对象编程探讨及比较

    2008-04-12 07:16:00
  • Python常见的pandas用法demo示例

    2022-09-16 12:55:04
  • python使用tkinter实现透明窗体上绘制随机出现的小球(实例代码)

    2023-04-29 11:00:24
  • layer弹出子iframe层父子页面传值的实现方法

    2024-04-19 09:56:10
  • 一文详解PyQt5中信号(Signal)与槽(Slot)

    2022-06-27 19:53:08
  • 重构Python代码的六个实例

    2023-08-07 02:10:14
  • 个人微信公众号接入ChatGPT的教程分享

    2023-04-08 00:34:02
  • python使用xlsx和pandas处理Excel表格的操作步骤

    2021-05-19 02:30:20
  • 详解Python利用configparser对配置文件进行读写操作

    2022-08-02 22:24:38
  • pygame游戏之旅 如何制作游戏障碍

    2021-03-05 00:16:28
  • asp之家 网络编程 m.aspxhome.com