PYQT5标签类控件没有象按纽自带的鼠标单击事件函数,只能用自定义信号来响应鼠标单击,常规只需重载鼠标按下或释放事件中处理逻辑代码即可,但如果有鼠标按下后在控件表面划过一区域再松开按键,则严格意义讲这不是单击了,是拖动了一矩形,如对逻辑有特殊的处理,就要判断到底鼠标的此动作是单击还是拖动,再分别处理对应的逻辑代码,下面作了一个判断的示例程序,供初学都参考。
import sys
import PyQt5
from PyQt5 import *
from PyQt5 import QtCore
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
#########################################################################################
class MyMainFrm(QMainWindow):
def __init__(self, parent=None):
super(MyMainFrm, self).__init__(parent)
self.setWindowIcon(QIcon("5G.JPG"))
self.setWindowTitle('鼠标单击标签控件示例')
self.resize(900,900)
self.label_Demo = MyLabelDemo(self)
# 设置label的尺寸
self.label_Demo.setMaximumSize(800,880)
self.label_Demo.setGeometry(10, 5, 800,880)
#为标签信号sign_clicked(成员变量定义详标签重载类中,名称可任意定)在主窗体中绑定一槽函数LabelClicked
self.label_Demo.sign_clicked.connect(self.LabelClicked)
#标签控件被单击后,主窗口响应标签信号singn_clicked信号的槽函数(发送信号处传来的三个参数:整数,整数,列表)
def LabelClicked(self,x,y,lst):
print(f'\n\n标签控件被鼠标单击了 {self.label_Demo.count} 次(注非鼠标按下)')
getx=x
gety=y
getlst=lst
print(f'主窗口接收标签类发来的信号sign_clicked传来的三个参数:x={getx},y={gety},列表变量{getlst}\n\n')
#重载主窗体的鼠标被按下事件(在其子窗体控件中要显示调用的super().mousePressEvent
# 分两种情况:一种是在主窗体上的标签控件发生按下鼠标事件后,在标签类中的mousePressEvent事件中显示调用了super().mousePressEvent
# 另一种是在标签控件外的本就属于主窗口没被遮盖的位置鼠标按下了直接调用此函数
def mousePressEvent(self,event):
if event.button() == Qt.LeftButton:
if(self.label_Demo.clickType == 1):
print(f'主窗体鼠标左键被按下事件(标签类中调用重载父类窗体的mousePressEvent事件):坐标 x={event.pos().x()},y={event.pos().y()}')
elif(self.label_Demo.clickType == 0):
print(f'主窗体鼠标左键被按下事件(主窗体本身的mousePressEvent事件,不是窗体上的子控件区域按下鼠标的左键):坐标 x={event.pos().x()},y={event.pos().y()}')
#重载标签类,
class MyLabelDemo(QLabel):
sign_clicked = QtCore.pyqtSignal(int,int,object) #注emit函数参数可以是任何数据类型(数量不限),且要在括号内标注引用时的参数类型,其中常规整数字符串用int str等(也可用object,信号槽函数接收端转换成对应类型),传递列表,字典,类对象时PYTHON的数据类型统一为object
#初始化
def __init__(self, text=''):
super(MyLabelDemo, self).__init__(text)
self.clickType=0 #示例:如果是标签类回调主窗口的鼠标下压事件时,此值为1,否则为0
self.count=0
#鼠标起点,鼠标终点
self.lastPoint = QPoint(0,0)
self.endPoint = QPoint(0,0)
#定义当前绘画类型
self.pix = QPixmap(800,880) #实例化QPixmap类
self.pix.fill(Qt.white) #白色画布填充
self.setPixmap(self.pix) # 把pix_img传递给label
self.noPatter = QPainter(self.pix).brush()
self.lst_demo=[0,1,2,'从标签控件通过信号传递列表值到主窗口','定义信号名称的参数一定要用object才不报错']
#重载绘图函数:根据选择设置,画鼠标单击位置的矩形
def paintEvent(self, event):
x1 = self.lastPoint.x()
y1 = self.lastPoint.y()
x2 = self.endPoint.x()
y2 = self.endPoint.y()
painter = QPainter(self)
#绘制画布到窗口指定位置处
pp = QPainter(self.pix)
pp.drawRect(x1,y1,abs(x2-x1),abs(y2-y1))
pp.drawText(10,20,880,60,Qt.AlignLeft,'重载标签类MyLabelDemo的一个实例化对象self.label_Demo,单击或下压拖动鼠标测试控件是单击还是拖动的判断示例')
painter.drawPixmap(0, 0, self.pix)
#########################################################################################
#鼠标按下事件重载
def mousePressEvent(self, event):
self.clickType = 1 #设置为1,告诉主窗口,我要调用你的鼠标下压事件了哦
super().mousePressEvent(event) #需显示调用其父类窗口的事件函数,主窗口才会响应,否则此鼠标事件只在此函数中执行完成即可,是否需要主窗口事件响应根据情况决定,好象一般不需要,除非在主窗口要对事件的值进行进定不响应才会用
print(f'重载标签类MyLabelDemo:鼠标被按下时的坐标:x={event.pos().x()},y={event.pos().y()}')
# 鼠标左键按下
if event.button() == Qt.LeftButton:
self.lastPoint = event.pos()
self.endPoint = self.lastPoint
self.clickType = 0
# 鼠标左键释放
def mouseReleaseEvent(self, event):
self.count+=1
self.endPoint = event.pos()
if event.button() == Qt.LeftButton:
print(f'重载标签类MyLabelDemo:鼠标左键释放时坐标:x={event.pos().x()},y={event.pos().y()}')
#判断此鼠标按下后释放是单击性质还是在标签控件有一个拖动动作
if(abs(self.endPoint.x()-self.lastPoint.x())<2 and abs(self.endPoint.y()-self.lastPoint.y())<2): #是单击不是拖动,容错1个像素
self.sign_clicked.emit(self.endPoint.x(),self.endPoint.y(),self.lst_demo) #传回三个参数,前两个是整型,后一个是列表(参数类型用object)
else:
print('\n在标签控件的鼠标按下及释放是一个拖动矩形框的动作,不应视为是单击事件,按拖动矩形框的方式画出一矩形\n')
#调用重新刷新标签控件,即时显示出所画的矩形和文本
self.update()
#########################################################################################
if __name__=="__main__":
app = QApplication(sys.argv)
myWin = MyMainFrm()
myWin.show()
sys.exit(app.exec())