PyQt5 事件处理机制

news2024/12/25 9:15:08

PyQt5 事件处理机制

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

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

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

  1. 重新实现事件函数,比如mousePressEvent(),keyPressEvent()等等。
  2. 重新实现QObject.event()。
  3. 安装时间过滤器。
  4. 在QApplication中安装事件过滤器。
  5. 重新实现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_()

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/46420.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Go语言中的值传递和引用传递 附: 内存地址分析

在学习Go语言函数部分遇到了引用传递和值传递&#xff0c;与C颇为类似&#xff0c;浅谈一下自己对Go语言中的值传递和引用传递的理解。 一、数组—值传递 我们用Go语言中的数组作为样例&#xff0c;来理解值传递的过程。 代码 package mainimport "fmt"func main…

[附源码]计算机毕业设计springboot基于Java的员工管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

[附源码]SSM计算机毕业设计校园闲置物品租赁系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Pytest接口测试框架实战项目搭建(二)

一、前言 业务系统的登录均要经过统一登录系统S&#xff0c;本篇演示统一登录处理&#xff0c;一个是内部业务系统C&#xff08;其余内部业务系统AB用的都是相同账号密码&#xff09;&#xff0c;一个是外部用户使用的系统W&#xff0c;因为账号密码以及headers信息都不一样&am…

DCDC--Burst Mode和Pulse Skipping Mode

1、Burst Mode和Pulse Skipping Mode&#xff08;PSM&#xff09;的区别 Burst Mode ≠ Pulse Skipping Mode&#xff0c;论坛有人认为Burst Mode就是Pulse Skipping Mode&#xff0c;这是不对的。 以LTC3624为例&#xff1a; Burst Mode operation provides the highest ef…

大数据(9h)FlinkSQL双流JOIN、Lookup Join

文章目录1、环境2、Temporal Joins2.1、基于处理时间&#xff08;重点&#xff09;2.1.1、设置状态保留时间2.2、基于事件时间3、Lookup Join&#xff08;重点&#xff09;4、Interval Joins&#xff08;基于间隔JOIN&#xff09;重点是Lookup Join和Processing Time Temporal …

SpringBoot+Vue实现前后端分离的餐饮点餐系统

文末获取源码 开发语言&#xff1a;Java 使用框架&#xff1a;spring boot 前端技术&#xff1a;JavaScript、Vue.js 、css3 开发工具&#xff1a;IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库&#xff1a;MySQL 5.7/8.0 数据库管理工具&#xff1a;phpstudy/Navicat JD…

线性表01- 数组与简易接口设计

线性表的定义 线性表: 具有n个相同类型元素的有限序列 n>0 线性表的元素特点是有索引, 可以通过索引快速查找到元素. a1是a2的前驱, a2是a1的后继 常见的线性表 数组链表栈队列哈希表 (散列表) 数组 数组是一种顺序存储的线性表, 所有的元素的内存地址是连续的. int arr…

Python用广义加性模型GAM进行时间序列分析

每当你发现一个与时间对应的趋势时&#xff0c;你就会看到一个时间序列。我们围绕广义加性模型GAM技术进行一些咨询&#xff0c;帮助客户解决独特的业务问题。研究金融市场表现和天气预报的事实上的选择&#xff0c;时间序列是最普遍的分析技术之一&#xff0c;因为它与时间有着…

matlab图像的运算有点运算、代数运算、逻辑运算和几何运算

1.图像的点运算 2.图像的代数运算 3.图像的逻辑运算 4.图像的几何运算 一、图像的点运算 图像的点运算&#xff1a;对图像中的每个像素值进行计算&#xff0c;从而改善图像显示效果的操作&#xff0c;常用于改变图像的灰度范围及分布&#xff0c;有时也被称为对比度增强和拉伸…

Arduino开发实例-DIY酒精浓度检测计

DIY酒精浓度检测计 在本文中,将详细介绍如何创建一个简单的酒精检测器。 它可以在各种应用领域中使用。市场上有许多先进的酒精传感器,价格合理,但我们在这里使用一些基本的微控制器来制作这个项目,如 Arduino、LED、蜂鸣器和 MQ3 酒精传感器。 1、MQ-3传感器介绍 MQ-3传…

外卖项目(项目优化2)11---读写分离

读&#xff1a;查询的操作 目录 一、Mysql主从复制 172 1.1Mysql主从复制_配置主库Master&从库Slave 173 配置&#xff1a;主库Master&#xff1a; 配置&#xff1a;从库Slave 二、读写分离案例 175 2.1背景 2.2Sharding-JDBC介绍 2.3读写分离案例---入门案例 17…

Magic Leap 2设计和开发幕后花絮

Magic Leap今年发布新款AR头显Magic Leap 2&#xff0c;相比于上一代Magic Leap 1&#xff0c;新品更专注于B端场景&#xff0c;自公布以来&#xff0c;Magic Leap不仅对公司策略、理念更加透明&#xff0c;也不断公开ML2产品设计背后的思考。相比于ML1&#xff0c;ML2的设计有…

里P7告诉你,接口测试真的很简单,有手就行

一、什么是接口测试&#xff1f; 所谓接口&#xff0c;是指同一个系统中模块与模块间的数据传递接口、前后端交互、跨系统跨平台跨数据库的对接。而接口测试&#xff0c;则是通过接口的不同情况下的输入&#xff0c;去对比输出&#xff0c;看看是否满足接口规范所规定的功能、…

windows bat批处理文件,实现某个软件的重启

bat批处理实现软件重启功能windows环境需要明确的概念按照启动文件xxx.exe去定位某个程序的Pid根据pid杀死某个进程根据exe文件启动某个软件bat示例&#xff0c;杀死软件进程并重启windows环境 我这里用的是win10企业版&#xff0c;在基础功能上和家庭版区别不大 需要明确的概…

19uec++多人游戏【基础AI导航】

首先把这一期的资源导入一下 创建一个球体类&#xff0c;继承于pawn类 为其添加静态组件 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category "Components")class UStaticMeshComponent * MeshComponent; #include "Components/StaticMeshComponent.h&qu…

具备统一门户功能的内网即时通讯软件才是发展趋势

作为企业领导&#xff0c;我们最害怕的就是下属工作效率不高&#xff0c;没办法为企业带来价值&#xff0c;有时候并不一定是员工自身存在问题&#xff0c;“工欲善其事&#xff0c;必先利其器“正好说明了&#xff0c;如果我们有能力在线的员工加上强大的办公软件辅助&#xf…

如何线上登记版权?

问题一&#xff1a;为什么要登记版权&#xff1f; 告诉你一个行业秘密&#xff0c;其实可以不用登记版权&#xff0c;为什么&#xff1f;因为作品自完成就自动拥有版权&#xff0c;作者可以自己选择登记与否&#xff0c;不登记对版权也没有影响。这里可能有人要问了&#xff0…

xss-labs/level12

这一关首先尝试以下 <script>alert(xss)</script> 不废话 直接看源代码 很明显发现第一个输出点被转义了 根本无法通过script标签来完成弹窗 然后依然是四个隐藏表单 我们可以先试一试在不用抓包工具的前提下 我们能不能将某个隐藏表单给显示出来 构造如下 &l…

Docker的常用基础命令(详细讲解)

首选需要大家搭建好Docker环境&#xff0c;没有环境的可以查看前面的详细讲解安装Docker引擎的文章&#xff08;在CentOS上安装Docker引擎_征服bug的博客-CSDN博客&#xff09; 首先是安装好Docker 引擎 一&#xff0c;如何启动与停止引擎服务 #启动docker systemctl start do…