详解PyQt5 事件处理机制
作者:SongYuLong的博客
PyQt为事件处理提供了两种机制高级的信号与槽机制,以及低级的事件处理机制,这篇文章主要介绍了PyQt5 事件处理机制,需要的朋友可以参考下
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_())
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 事件处理机制的文章就介绍到这了,更多相关PyQt5 事件处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!