PyQt5桌面应用开发(19):事件过滤器

news2024/12/23 1:54:36

本文目录

  • PyQt5桌面应用系列
  • 再来点事件
  • 事件过滤器
  • 例子
    • 这是什么恶毒巫术?
    • 需求分析
    • 代码
    • 额外的细节知
  • 总结

PyQt5桌面应用系列

  • PyQt5桌面应用开发(1):需求分析
  • PyQt5桌面应用开发(2):事件循环
  • PyQt5桌面应用开发(3):并行设计
  • PyQt5桌面应用开发(4):界面设计
  • PyQt5桌面应用开发(5):对话框
  • PyQt5桌面应用开发(6):文件对话框
  • PyQt5桌面应用开发(7):文本编辑+语法高亮与行号
  • PyQt5桌面应用开发(8):从QInputDialog转进到函数参数传递
  • PyQt5桌面应用开发(9):经典布局QMainWindow
  • PyQt5桌面应用开发(10):界面布局基本支持
  • PyQt5桌面应用开发(11):摸鱼也要讲基本法,两个字,16
  • PyQt5桌面应用开发(12):QFile与线程安全
  • PyQt5桌面应用开发(13):QGraphicsView框架
  • PyQt5桌面应用开发(14):数据库+ModelView+QCharts
  • PyQt5桌面应用开发(15):界面动画
  • PyQt5桌面应用开发(16):定制化控件-QPainter绘图
  • PyQt5桌面应用开发(17):类结构+QWebEngineView
  • PyQt5桌面应用开发(18):自定义控件界面设计与实现
  • PyQt5桌面应用开发(19):事件过滤器

再来点事件

利用PyQt或者Qt进行界面设计和GUI程序编制时,其核心的是显示一个可以交互或者展示信息的图形界面。因此,事件是这里面非常核心和值得反复思考和学习的内容。事件是图形界面系统更新界面的核心。Qt采用QObject的方式为每一个对象配置了定时器和事件处理循环,调用一个对象的exec()
(在PyQt中是exec_)就会启动这个循环,然后定时来处理相应的时间,包括系统中的事件、用户的操作和逻辑上的时间(也就是信号)。当事件跨线程时,Qt还通过线程安全的事件队列来保证对相关信息的访问和改变具备一致性。

对于界面上跟用户交互的时间,有三类处理方法:

  1. 处理事件的方法一:重载event函数,调用QEvent.type()与QEvent的枚举进行比较
  2. 处理事件的方法二:重载各种xxxEvent函数,针对特定事件实现逻辑
  3. 处理事件的方法三:注册事件过滤器

可以简单比较这三种方法,重载event和事件过滤器中需要自己判断事件的类型,调用QEvent对象的type方法,并于QtEvent中定义的枚举变量进行对比,之后可能还需要对QEvent对象进行手动的转换,例如鼠标移动事件里,QEvent实际上引用的是QMouseMoveEvent;重载特定时间对应的事件虚函数,则无需进行比较,对应的事件类也是准确的子类。

方法特点
重载event函数一次处理所有事件;需要自己编写事件类型判断并做转换;调整逻辑难以清晰表达
重载特定事件函数逻辑清晰;只针对特定的事件,按键、鼠标按键、鼠标移动等;根据情景调整事件处理的逻辑实现起来比较不清晰
事件过滤器需要处理事件发送对象;需要自行判断事件类型并做类型转换;很方便的调整事件是否触发

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JFTNJMHp-1685755483481)(imgs/events.png)]

事件过滤器

对于重载函数,前面的几篇文章中也多多少少的涉及到了,也非常好理解,就是面向对象中的函数多态的典型用法。事件循环中针对QWidget中虚函数接口编程,而各个子类中重载的虚函数则实现实际的逻辑。这个实际的逻辑在编码的时候就已经定义好,如果需要切换不同的逻辑,则需要在函数中定义各种判断条件,这些判断条件就会增加程序中不同组件之间的耦合,在比较简单的场合,这是很容易实现的。如果判断的逻辑比较复杂,从设计模式的依赖倒置等方法出发,则应该将不同的逻辑提取出来,实现单独的组件。这就是事件过滤器。

事件过滤器需要实现一个函数def eventFilter(self, a0: QObject, a1: QEvent):
,对于实现这个函数的兑现,就可以通过installEventFilterremoveEventFilter来动态调整是否启用eventFilter所包含的事件处理逻辑。

例子

这是什么恶毒巫术?

接下来,我们来一点点光影魔法(下面的内容对眼睛极为不友好……)

在这里插入图片描述

需求分析

要实现的报表:

  1. 斜纹、圈纹和闪光

交互:

  1. 鼠标移动,图案变幻
  2. 滚轮:调整图案密集程度
  3. 键盘事件:调整图案形式
  4. 键盘事件:启动和停止闪瞎

代码

import sys

import numpy as np
from PyQt5.QtCore import QEvent, Qt, QObject
from PyQt5.QtGui import QColor, QGradient, QRadialGradient, QLinearGradient, QConicalGradient, QWheelEvent
from PyQt5.QtWidgets import QApplication, QWidget


def random_color() -> QColor:
    return QColor(*np.random.randint(0, 255, 4))


class Pattern(int):
    Linear = 0
    Radial = 1
    Conical = 2


class EventWidget(QWidget):
    def __init__(self, parent=None):
        super(EventWidget, self).__init__(parent)
        self.installEventFilter(self)
        self.setMouseTracking(True)
        palette = self.palette()
        palette.setBrush(self.backgroundRole(), QGradient(QGradient.Blessing))
        self.setPalette(palette)

        self.pattern = Pattern.Radial
        self.pattern_count = 12

        self.setToolTip("L: 更换花纹;C+space:停止;space:启用;鼠标滚轮:增加/减少条纹")

    def eventFilter(self, a0: QObject, a1: QEvent):

        if a0 == self:
            if a1.type() == QEvent.MouseMove:
                palette = self.palette()
                rect = self.geometry()
                gradient = None
                if self.pattern == Pattern.Linear:
                    gradient = QLinearGradient(0, 0, rect.width(), rect.height())
                if self.pattern == Pattern.Radial:
                    gradient = QRadialGradient(rect.width() / 2, rect.height() / 2, rect.width() / 2)
                if self.pattern == Pattern.Conical:
                    gradient = QConicalGradient(rect.width() / 2, rect.height() / 2, 0)
                n = self.pattern_count

                for i in range(n + 1):
                    gradient.setColorAt(i / n, random_color())
                gradient.setSpread(QGradient.RepeatSpread)
                palette.setBrush(self.backgroundRole(), gradient)

                self.setPalette(palette)
            if a1.type() == QEvent.Wheel:
                a1: QWheelEvent
                if a1.angleDelta().y() > 0:
                    self.pattern_count += 1
                else:
                    self.pattern_count -= 1
                    if self.pattern_count <= 0:
                        self.pattern_count = 100

        return super(EventWidget, self).eventFilter(a0, a1)

    def event(self, a0: QEvent) -> bool:

        if a0.type() == QEvent.KeyPress and a0.key() == Qt.Key_Tab:
            rect = self.geometry()
            if a0.modifiers() == Qt.ControlModifier:
                dx = -10
            else:
                dx = 10
            self.setGeometry(rect.x() + dx, rect.y(), rect.width(), rect.height())
        if a0.type() == QEvent.KeyPress and a0.key() == Qt.Key_Space:
            if a0.modifiers() == Qt.ControlModifier:
                self.removeEventFilter(self)
            else:
                self.installEventFilter(self)
        if a0.type() == QEvent.KeyPress and a0.key() == Qt.Key_L:
            self.pattern = (self.pattern + 1) % 3
        if a0.type() == QEvent.KeyPress and a0.key() == Qt.Key_K:
            self.pattern = (self.pattern - 1) % 3
        return super(EventWidget, self).event(a0)


if __name__ == '__main__':
    app = QApplication([])

    win = EventWidget()

    win.resize(600, 600)
    win.setWindowTitle("这是什么恶毒巫术!")
    win.show()

    sys.exit(app.exec_())

额外的细节知

  1. Gradient设置渐变画刷
    1. QLinearGradient:线性变化
    2. QRadialGradient:径向变化
    3. QConicalGradient:圆周变化
  2. 鼠标滚轮事件wheelEvent函数
    1. QWheelEvent
    2. QEvent.Wheel
    3. angleDelta().y()上下的滚轮调整数值
  3. mouseMoveEvent函数
    1. QMouseMoveEvent
    2. QEvent.MouseMove
    3. setMouseTracking(True):无需按下按键触发mouseMoveEvent

总结

  1. 事件过滤器是一种可以在运行时改变的事件处理机制;
  2. 只需要实现接口eventFilter函数,就能作为过滤器安装和卸载;
  3. Gradient渐变画刷还是不要用了……会被打

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

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

相关文章

从零到无搭建Vue项目及代码风格规范

注&#xff1a;已经有vue项目的可以跳过项目初始化 Vue项目搭建 环境搭建 安装nvm 方便后续切换不通的node版本 nvm官网 傻瓜安装就行 或者搜下自己&#xff08;非本文重点&#xff09;nvm 安装好后 安装一个Node版本 本文使用的 有了环境开始创建Vue项目 打开命令行 cmd n…

Redis底层学习(五)—存储类型-Set篇

文章目录 特点具体服务器操作命令底层结构应用场景 特点 适⽤场景&#xff1a;存储有去重需求的数据&#xff0c;⽐如&#xff1a;针对⼀篇⽂章⽤户进⾏点赞操作。 它的特点是内部元素⽆序且不重复。它的内部实现相当于⼀个特殊的字典&#xff0c;字典中所有的 value 的值都为…

这么好看的头像,岂不拿下!

❝ 如此好看的头像&#xff0c;怎么能不喜欢&#xff1f;&#xff1f;&#xff1f; ❞ 代码放在了最后 后续还会出一个工具&#xff0c;以便于随时打开下载。 看上述的头像是不是还是很不错的。看着网站还是✨✨每天都会有更新的✨✨。 所以&#xff0c;我动手了&#xff0c;下…

5.2 案例引入

博主简介&#xff1a;一个爱打游戏的计算机专业学生博主主页&#xff1a; 夏驰和徐策所属专栏&#xff1a;算法设计与分析 1.什么是大数据时代的到来&#xff1f; 大数据时代指的是在现代社会中&#xff0c;产生和积累的数据规模庞大、速度快、种类多样的时代。随着计算机技术…

《商用密码应用与安全性评估》第四章密码应用安全性评估实施要点4.4密码应用安全性评估测评过程指南

目录 概述 1.基本原则 2.风险测评控制 3.测评过程 密码应用评估方案 1.主要内容 1&#xff09;密码应用解决方案评估要点 2&#xff09;实施方案评估要点 3&#xff09;应急处置方案评估要点 2.主要任务 3.密码应用方案评估的输出文档 测评准备活动 1.测评准…

不愧是阿里,扣的真细。

铜三铁四已经过去了&#xff0c;今天的行情虽然没有以前好&#xff0c;但是相比去年来说也算是好了一些了。有一些人已经在这个招聘季拿到了不错的Offer了。 今天给大家分享一份面经&#xff0c;今天这位朋友的背景是Java五年本&#xff0c;2023年前被毕业后投入了面试大军怀抱…

Baseline Profile 安装时优化在西瓜视频的实践

‍ 动手点关注 干货不迷路 背景 在Android上&#xff0c;Java/Kotlin代码会编译为DEX字节码&#xff0c;在运行期由虚拟机解释执行。但是&#xff0c;字节码解释执行的速度比较慢。所以&#xff0c;通常虚拟机会在解释模式基础上做一些必要的优化。 在Android 5&#xff0c;Goo…

chatgpt赋能python:Python列表:完整介绍与使用指南

Python列表&#xff1a;完整介绍与使用指南 Python是一种非常受欢迎的编程语言&#xff0c;而Python列表是Python编程中最基本的数据结构之一。列表在Python中的使用频率极高&#xff0c;因为列表可以存储许多不同类型的数据&#xff0c;并且可以很方便地进行操作和修改。在本…

Unity Addressables学习笔记(2)---创建远程服务器对象

1.先创建对象 我的做法是&#xff1a; 先拖动一张图片到Resources/img下就是我选中的这张文件夹 2.把图片拖动到Hierarchy里变成一个对象&#xff0c;再把对象拖动到Resources/prefabs里&#xff0c;图片里的单词敲错了哈哈哈哈。 这样这个图片就变成了预制体&#xff0c;然…

AMD在数据中心领域举步维艰,竞争越来越难

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 数据中心业务举步维艰 2023年第一季度&#xff0c;AMD的数据中心业务收入为13亿美元&#xff0c;几乎没有同比增长&#xff0c;反而环比下降了22%。与此同时&#xff0c;它的主要竞争对手英伟达(NVDA)却获得了越来越多的订…

行为型设计模式04-状态模式

✨作者&#xff1a;猫十二懿 ❤️‍&#x1f525;账号&#xff1a;CSDN 、掘金 、个人博客 、Github &#x1f389;公众号&#xff1a;猫十二懿 状态模式 1、状态模式介绍 状态模式&#xff08;State&#xff09;是一种行为型设计模式&#xff0c;当一个对象的内在状态改变时…

python---条件语句(1)

顺序语句 按照写的顺序执行 条件语句 条件语句的一些注意事项: 1.情况1 2.情况2 bbb已经不属于条件语句中的内容了 3.情况3 通常使用4个空格或一个制表符tab来表示! if语句的嵌套 当有多级条件嵌套时,当前的语句属于哪个代码块,完全取决于缩进的级别.

SOFA Weekly|SOFAArk 社区会议预告、Layotto 社区会议回顾与预告、社区本周贡献

SOFA WEEKLY | 每周精选 筛选每周精华问答&#xff0c;同步开源进展 欢迎留言互动&#xff5e; SOFAStack&#xff08;Scalable Open Financial Architecture Stack&#xff09;是蚂蚁集团自主研发的金融级云原生架构&#xff0c;包含了构建金融级云原生架构所需的各个组件&am…

PostgreSql根据给的时间范围统计15分钟粒度、小时粒度、天粒度、周粒度、月粒度工单

PostgreSql根据给的时间范围统计15分钟粒度、小时粒度、天粒度、周粒度、月粒度工单 说明实现15分钟粒度工单统计小时粒度工单统计天粒度工单统计周粒度工单统计月粒度工单统计 说明 项目有个需求是统计故障工单每15分钟、每小时、每天、每周和每月共有多少工单。 这里先做个笔…

JavaEE进阶(统一功能处理)6/2

目录 1.使用拦截器实现用户登录的校验功能 2.统一数据格式的返回 3.统一异常的返回 1.使用拦截器实现用户登录的校验功能 Spring拦截器 关键步骤1.实现HandlerInterceptor接口 2.重写preHeadler方法&#xff0c;在方法中编写自己的业务代码 将拦截器添加到配置文件中&#xf…

【剑指offer】二维数组中的查找(详细解析)

文章目录 题目思路代码实现 题目 题目链接入口&#xff1a;牛客&#xff1a;JZ4 二维数组中的查找 思路 1.核心考点 &#xff08;1&#xff09; 数组相关&#xff1a;二维数组&#xff08;矩阵&#xff09;。 &#xff08;2&#xff09; 特性观察&#xff1a;在一个二维数组…

如何使用宝塔面板搭建网站(最后一步!上传文件至宝塔面板)

这里就是我们搭建宝塔面板的最后一步了&#xff0c;把我们的PHP文件上传到宝塔面板上&#xff0c;就可以通过因特尔网络访问我们的网址了。 第一步&#xff1a;基础安装 必须是Linux服务器 不支持window服务器 最低要求配置1核1G当然再低些也能运行但是不建议 要求服务器环…

值得收藏 | 脑机交互作用研究

神经损伤和疾病对许多人的生活产生了巨大的影响&#xff0c;导致了许多运动障碍和日常任务无法独立完成。皮质假体系统通过脑机接口&#xff08;BCI&#xff09;接收一个动作命令来执行所需的位置&#xff0c;从而使得经历神经损伤的人能够实现部分功能恢复。BCI技术可以在侵入…

chatgpt赋能python:Python创建二维列表的方法

Python创建二维列表的方法 Python是一种高级编程语言&#xff0c;它的灵活性和功能强大的库使其成为数据科学和机器学习的最佳工具之一。其中一个常用的数据结构是二维列表&#xff0c;本文将介绍如何在Python中创建一个二维列表。 什么是二维列表&#xff1f; 在Python中&a…

华为OD机试真题 Java 实现【表示数字】【牛客练习题】

一、题目描述 将一个字符串中所有的整数前后加上符号“*”&#xff0c;其他字符保持不变。连续的数字视为一个整数。 数据范围&#xff1a;字符串长度满足1≤n≤100 。 二、输入描述 输入一个字符串。 三、输出描述 字符中所有出现的数字前后加上符号“*”&#xff0c;其…