【PyQt】(自制类)处理鼠标点击逻辑
写了个自认为还算不错的类,用于简化mousePressEvent
、mouseMoveEvent
和mouseReleaseEvent
中的鼠标信息。
功能有以下几点:
鼠标当前状态
,包括鼠标左/中/右键和单击/双击/抬起鼠标防抖
(仅超出一定程度时才判断鼠标发生了移动),灵敏度可设置;鼠标长按
(在鼠标长按并且未发生移动时触发),时长可设置;鼠标双击
(两次点击的时间间隔足够小时判断为双击),时长可设置;鼠标偏移量
,仅鼠标按下时有效,可返回自点击时的总偏移量,也可返回与上次鼠标事件之间的相对偏移量
补充:
这个自制类在多键按下时会产生歧义,也就是没法处理有如刁难一般的操作,像是右键拖拽然后左键来添乱之类的。本来是想再重新写份代码以填补这个缺陷的,但想想就有点怪,什么场合下才需要满足这种怪异的操作。
自制类XJ_MouseStatus
:
#XJ_MouseStatus.py
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtCore import QPoint,Qt,QObject
from PyQt5.QtGui import QMouseEvent__all__=['XJ_MouseStatus']
class XJ_MouseStatus(QObject):#mousePressEvent、mouseMoveEvent和mouseReleaseEvent特供。只处理单键(多键行为请在外部代码控制)longClick=pyqtSignal()#鼠标原地不动长按时触发__antiJitter=5#防抖,当鼠标点击位置与鼠标当前位置的曼哈顿距离不超过该值时仍将鼠标视为不动状态__doubleClickInterval=500#双击间隔(ms)__longPressInterval=500#长按间隔(ms)__record={'lastPress':None,#上一次按下时的信息'lastMouse':None,#上一次的鼠标信息'currMouse':None,#当前鼠标信息}__press=[QMouseEvent.MouseButtonRelease,QMouseEvent.MouseButtonPress,QMouseEvent.MouseButtonDblClick]#偷懒用的__move=False#用于判断是否长按__timerID=0#鼠标按下时对应的定时器class __Data:pos=None#鼠标位置btn=None#鼠标按键(左中右)pressStatus=None#鼠标当前按下状态(单双击/抬起)timeStamp=None#鼠标事件时间刻def __init__(self,event):self.pos=event.globalPos()#这里不用pos是为了防暴毙self.btn=event.button()self.pressStatus=event.MouseButtonReleaseself.timeStamp=event.timestamp()def __init__(self,*arg):super().__init__(*arg)record=self.__record.copy()fakeEvent=QMouseEvent(QMouseEvent.MouseButtonRelease,QPoint(0,0),Qt.NoButton,Qt.NoButton,Qt.NoModifier)data=self.__Data(fakeEvent)data.timeStamp-=self.__doubleClickInterval#小防,避免开局单击时触发双击行为record['lastMouse']=datarecord['currMouse']=datarecord['lastPress']=dataself.__record=recorddef timerEvent(self,event):record=self.__recordpress=self.__presstId=event.timerId()cId=self.__timerIDself.killTimer(event.timerId())if(cId==tId):#当前定时器if(not self.__move and record['currMouse'].pressStatus!=press[0]):#未发生移动,未抬起鼠标,触发长按信号self.longClick.emit()def Set_DoubleClickInterval(self,interval):#设置双击时间间隔(ms)self.__doubleClickInterval=intervaldef Set_LongPressInterval(self,interval):#设置长按时间间隔(ms)self.__longPressInterval=intervaldef Set_AntiJitter(self,val):#设置防抖值self.__antiJitter=val if val>0 else 0def Get_Position(self):#返回鼠标坐标。是屏幕坐标(global),需要使用QWidget.mapFromGlobal(QPoint)自行转换为控件相对坐标return self.__record['currMouse'].posdef Get_PressButtonStatus(self):#返回当前鼠标的键(左中右)以及按下状态(单击/双击/抬起)return self.__record['currMouse'].btn,self.__record['currMouse'].pressStatusdef Get_MoveDelta(self,total=True,strict=True):#返回鼠标移动量(仅鼠标按下时有效),为QPoint对象press=self.__pressrecord=self.__recorddata_curr=record['currMouse']if(data_curr.pressStatus!=press[0]):#说明鼠标按下if(not strict or self.__move):#严格模式下,仅判定发生移动时计算移动量p1=record['currMouse'].posif(total):p2=record['lastPress'].poselse:p2=record['lastMouse'].posreturn QPoint(p1.x()-p2.x(),p1.y()-p2.y())return QPoint(0,0)def Get_HasMoved(self):#判断是否发生移动(毕竟用Get_MoveDelta来判断移动的发生是有点麻烦,还不如多一个函数return self.__movedef Opt_Update(self,event):#更新状态press=self.__pressrecord=self.__recorddata_curr=self.__Data(event)if(event.type()==press[1] or event.type()==press[2]):#单/双击self.__move=Falsedata_old=record['lastPress']data_curr.pressStatus=press[1]if(data_old.btn==data_curr.btn):#同键位按下if(data_curr.timeStamp-data_old.timeStamp<self.__doubleClickInterval):#在时间间隔内if(data_old.pressStatus!=press[2]):#没有双击过data_curr.pressStatus=press[2]#双击record['lastPress']=data_currrecord['lastMouse']=data_currrecord['currMouse']=data_currself.__timerID=self.startTimer(self.__longPressInterval)else:#移动/抬起data_curr.btn=event.buttons()data_curr.pressStatus=record['lastMouse'].pressStatusif(event.type()==press[0]):#抬起if(data_curr.btn==Qt.NoButton):#确保无按键按下时设置为Releasedata_curr.pressStatus=press[0]data_curr.btn=event.button()else:#移动(QMouseEvent.MouseMove)if(data_curr.pressStatus!=press[0] and not self.__move):#判断有无发生拖拽delta=self.Get_MoveDelta(strict=False)if(abs(delta.x())+abs(delta.y())>self.__antiJitter):self.__move=Truerecord['currMouse'].pos=record['lastPress'].posrecord['lastMouse']=record['currMouse']record['currMouse']=data_curr
测试代码与运行结果:
与鼠标相关的部分枚举量:
- 单击
QMouseEvent.MouseButtonPress
- 双击
QMouseEvent.MouseButtonDblClick
- 抬起
QMouseEvent.MouseButtonRelease
- 左键
Qt.LeftButton
- 中键
Qt.MidButton
- 右键
Qt.RightButton
#Main.py
import sys
from PyQt5.QtWidgets import QApplication,QWidget
from XJ_MouseStatus import *class Test(QWidget):__mouseStatus=Nonedef __init__(self,*arg):super().__init__(*arg)ms=XJ_MouseStatus()ms.longClick.connect(lambda:print("<LongClick!>"))self.__mouseStatus=msdef __EasyPrint(self):press={QMouseEvent.MouseButtonRelease:"Release",QMouseEvent.MouseButtonPress:"Press",QMouseEvent.MouseButtonDblClick:"DblClick",}button={Qt.LeftButton:'Left',Qt.MidButton:'Middle',Qt.RightButton:'Right',}tPoint=lambda point:(point.x(),point.y())tBtn=lambda btn:[button[key] for key in button if key&btn]tBtnStatus=lambda status:(tBtn(status[0]),press[status[1]])ms=self.__mouseStatuspos=tPoint(self.mapFromGlobal(ms.Get_Position()))moveDelta=tPoint(ms.Get_MoveDelta())btnStatus=tBtnStatus(ms.Get_PressButtonStatus())print(f'pos{pos},\tdelta{moveDelta},\t{btnStatus[0]}-{btnStatus[1]}')if(btnStatus[1]=='Release'):print()def mousePressEvent(self,event):self.__mouseStatus.Opt_Update(event)self.__EasyPrint()def mouseMoveEvent(self,event):self.__mouseStatus.Opt_Update(event)self.__EasyPrint()def mouseReleaseEvent(self,event):self.__mouseStatus.Opt_Update(event)self.__EasyPrint()if __name__=='__main__':app = QApplication(sys.argv)t=Test()t.show()sys.exit(app.exec())
本文发布于CSDN,未经个人允许不得私自转载:https://blog.csdn.net/weixin_44733774/article/details/134349820
相关文章:

【PyQt】(自制类)处理鼠标点击逻辑
写了个自认为还算不错的类,用于简化mousePressEvent、mouseMoveEvent和mouseReleaseEvent中的鼠标信息。 功能有以下几点: 鼠标当前状态,包括鼠标左/中/右键和单击/双击/抬起鼠标防抖(仅超出一定程度时才判断鼠标发生了移动),灵…...

JAVA IDEA 下载
超简单步骤一: IntelliJ IDEA 官方下载链接 点击以上链接进入下图,点击下载 继续点下载,然后等待下载完后打开安装包即可 步骤二: 打开下好的安装包,点击Browse...我们把它下载到自己喜欢的地方(主要是别占…...

DevOps简介
DevOps简介 1、DevOps的起源2、什么是DevOps3、DevOps的发展现状4、DevOps与虚拟化、容器 1、DevOps的起源 上个世纪40年代,世界上第一台计算机诞生。计算机离不开程序(Program)驱动,而负责编写程序的人,被称为程序员&…...

体验前所未有的显示器管理体验:BetterDisplay Pro Mac
在现代的数字化时代,显示器是我们日常生活和工作中不可或缺的一部分。从笔记本电脑到台式机,从平板电脑到手机,几乎所有的电子设备都配备了显示器。然而,对于专业人士和从事设计行业的人来说,仅仅依靠系统自带的显示器…...
python用pyinstaller打包exe,去掉黑窗口
使用Python编写程序将Python脚本打包成可执行文件(EXE),但是会有一个命令框产生,很烦,所以,去掉这个框 1,安装pyinstaller pip install pyinstaller2,打包产生cmd命令框 pyinstaller --onefi…...

如何关闭Windows Defender(亲测可行!!非常简单)
一、背景 Windows Defender(简称WD)真的太讨厌了,经常给你报你下载的文件是病毒,且不说真的是不是病毒,它都不询问直接删。 另外聚资料显示WD还会不合时宜地执行扫描导致系统变慢(不会在合适的、空闲的时…...
【objectarx.net】创建多重引线
创建多重引线...
【objectarx.net】创建组,列出所有组,查找实体所在的组
创建组,列出所有组...

Llama2通过llama.cpp模型量化 WindowsLinux本地部署
Llama2通过llama.cpp模型量化 Windows&Linux本地部署 什么是LLaMA 1 and 2 LLaMA,它是一组基础语言模型,参数范围从7B到65B。在数万亿的tokens上训练的模型,并表明可以专门使用公开可用的数据集来训练最先进的模型,而无需求…...

Coding面试题之手写线程池
原理图 JDK线程池原理 实现代码 1.线程类(PoolThread) 这个类用于执行任务队列中的任务。 public class PoolThread extends Thread {private final Queue<Runnable> taskQueue;private boolean isStopped false;private long lastTaskTime …...
【objectarx.net】删除零长度曲线和获取零长度曲线的数量
删除零长度曲线和获取零长度曲线的数量...

Win11专业版安装Docker Desktop,并支持映射主机的gpu
一、Windows环境下安装 Docker 必须满足: 1. 64位Windows 11 Pro(专业版和企业版都可以) 2. Microsoft Hyper-V,Hyper-V是微软的虚拟机,在win11上是自带的,我们只需要启动就可以了 二、下载Docker Desktop安装包 方式一:进入官网下载 https://docs.docker.com/desktop…...

Mac代码文本编辑器Sublime Text 4
Sublime Text 4 for Mac拥有快速响应的功能,可以快速加载文件和执行命令,并提供多种语言支持,包括C 、Java、Python、HTML、CSS等。此外,该编辑器还支持LaTeX、Markdown、JSON、XML等技术领域。 Sublime Text 4 for Mac的插件丰富…...

MATLAB中plot函数用法
目录 语法 说明 向量和矩阵数据 表数据 其他选项 示例 创建线图 绘制多个线条 根据矩阵创建线图 指定线型 指定线型、颜色和标记 在特定的数据点显示标记 指定线宽、标记大小和标记颜色 添加标题和轴标签 绘制持续时间并指定刻度格式 基于表绘制坐标 在一个轴…...
win10 安装vscode
1 Download Visual Studio Code - Mac, Linux, Windows 2 this user installer is not meant to be run as an administrator . if ou would like to install vs code for all users i this sys download the system installer instead form are u want to con 提示的意思是&a…...

MATLAB中Arrow 属性说明
目录 颜色和样式 位置 Arrow 属性是箭头的外观和行为。 Arrow 属性控制 Arrow 对象的外观和行为。通过更改属性值,可以修改箭头的特定方面。使用圆点表示法查询和设置属性。 ar annotation("arrow"); c ar.Color; ar.Color "red"; 颜色和…...

MYSQL 慢查询和慢查询日志
在数据库管理中,慢查询是指执行时间较长的 SQL 查询语句。这类查询可能导致系统性能下降,影响用户体验。为了帮助识别和解决这些性能问题,数据库管理系统通常提供了慢查询日志,用于记录执行时间超过一定阈值的查询。本文将深入探讨…...

Longhorn跨AZ实现存储高可用
Longhorn跨AZ实现存储高可用 longhorn基础组件功能及其作用这里就不做介绍了 方案一 Longhorn跨AZ的高可用的就是一个PVC的replicas 均匀打散的不同的AZ区域之间,这样当某个AZ挂掉后,engine会立即使用另外一个数据副本,并重建这个副本&…...

maven 私有仓库配置
1.整体库信息 2.配置阿里云库 (可以配置多个库,再引用代理库) 3.建立自己的 发布,快照库 4.建立自由的公共库- 引用所有需要的库 5.maven setting 中配置 用户名密码 <server><id>mv-releases</id><usernam…...
TypeScript: 判断两个数组的内容是否相等
一、直接遍历 // 1.直接遍历 const arr1: any[] ["apple", "banana", NaN]; const arr2: any[] ["apple", NaN, "banana"];function fn1(arr1: any[], arr2: any[]) {// Array.some(): 有一项不满足,返回falseif (arr1.…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...