详解PyQt5 事件处理机制

 更新时间:2022年11月30日 10:29:12   作者: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 事件处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python序列化模块之pickle与json详解

    Python序列化模块之pickle与json详解

    这篇文章主要为大家介绍了Python中常用的两个序列化模块:pickle序列化和json序列化。文中的示例代码讲解详细,感兴趣的小伙伴可以学习一下
    2022-05-05
  • 基于python历史天气采集的分析

    基于python历史天气采集的分析

    今天小编就为大家分享一篇基于python历史天气采集的分析,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-02-02
  • Python property函数的具体使用

    Python property函数的具体使用

    property()函数是Python中用于创建可管理属性的重要工具,它可以实现数据封装、访问控制、属性计算等功能,本文就来介绍一下如何使用,感兴趣的可以了解一下
    2024-02-02
  • python基于turtle绘制几何图形

    python基于turtle绘制几何图形

    turtle又称为海龟绘图,是Wally Feurzeig, Seymour Papert 和 Cynthia Solomon 于 1967 年所创造的 Logo 编程语言的python实现。turtle是基于tkinter图形界面设计的。
    2021-06-06
  • python+Word2Vec实现中文聊天机器人的示例代码

    python+Word2Vec实现中文聊天机器人的示例代码

    本文主要介绍了python+Word2Vec实现中文聊天机器人,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • python数据写入列表并导出折线图

    python数据写入列表并导出折线图

    这篇文章主要介绍了python数据写入列表并导出折线图,文章以举例展开对文章主题的介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-01-01
  • Tensorflow实现酸奶销量预测分析

    Tensorflow实现酸奶销量预测分析

    这篇文章主要为大家详细介绍了Tensorflow酸奶销量预测分析,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-07-07
  • Python过滤txt文件内重复内容的方法

    Python过滤txt文件内重复内容的方法

    今天小编就为大家分享一篇Python过滤txt文件内重复内容的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-10-10
  • python编程简单几行代码实现视频转换Gif示例

    python编程简单几行代码实现视频转换Gif示例

    这篇文章主要为大家介绍了简单使用几行python代码就可以实现将视频转换Gif的示例过程,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-10-10
  • python实现俄罗斯方块游戏

    python实现俄罗斯方块游戏

    这篇文章主要为大家介绍了python实现俄罗斯方块游戏的详细代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06

最新评论