PyQt5自定义组件功能,包括鼠标事件与键盘事件(PyQt5.QtWidgets))
引言
QtWidgets 是PyQT5中负责UI组件的模块。
要组建自定义组件功能需要QtWidgets中继承组件,并自定义功能。
本文例子采用鼠标移入Label显示弹窗。
定义组件类,继承自QtWidgets
class WatchLabel(QtWidgets.QLabel):#自定义组件WatchLabel,继承自QLabel
def __init__(self,parent = None):
super(WatchLabel, self).__init__(parent)
为自定义组件添加功能
class WatchLabel(QtWidgets.QLabel):#自定义组件WatchLabel,继承自QLabel
def __init__(self,parent = None):
super(WatchLabel, self).__init__(parent)
def enterEvent(self, *args, **kwargs):#定义鼠标移入事件
def leaveEvent(self, *args, **kwargs):#定义鼠标移出事件
鼠标事件
处理鼠标事件的频率不低于键盘事件。包括按下、松开鼠标按键;移动鼠标到特定区域或离开特定区域;更改鼠标指针的形状,等等。
-
按下、松开鼠标按键
mousePressEvent (self, event) - 鼠标键按下时调用;
mouseReleaseEvent (self, event) - 鼠标键公开时调用;
mouseDoubieCiickEvent (self, event) - 双击鼠标时调用。 -
鼠标指针
要处理鼠标指针的移动,需要重载mouseMoveEvent(self,event)方法。缺省情况下,只有按下鼠标键移动时,才会调用mouseMoveEvent( )。如果要处理包括普通的移动,需要以参数为True调用setMouseTracking() 方法。如果要处理窗口中鼠标移动的事件,需要调用grabMouse( )方法。event对象的pos( )返回值为相对控件的坐标,要转换成相对父控件或屏幕的坐标,需要调用QWidget类的以下方法:
mapToGlobal (QPoint) - 将窗口坐标转换成屏幕坐标;
mapFromGlobal(QPoint) - 将屏幕坐标转换成窗口坐标;
mapToParent(QPoint) - 将窗口坐标转换成父窗口坐标。如果没有父窗口,则相当于mapToGlobal (QPoint);
mapFromParent(QPoint) - 将父窗口坐标转换成窗口坐标。如果没有父窗口,则相当于mapFromGlobal(QPoint);
mapTo (QWidget, QPoint) - 将窗口坐标转换成 QWidget父窗口坐标;
mapFrom (QWidget, QPoint) - 将 QWidget父窗口坐标转换成窗口坐标 -
鼠标移进和移出控件
enterEvent (self, event) -鼠标进入控件;
leaveEvent (self, event) - 鼠标离开控件; -
滚动鼠标
wheelEvent (self, event)方法可用来处理鼠标滚动事件。event是一个QWheelEvent对象,包含滚轮操作的相关信息。有以下方法可调用:angleDelta( ) - 返回QPoint对象,为滚轮转过的数值,单位为1/8度。例如:
angle=event.angleDelta( ) /8
angleX=angle.x()
angleY=angle.y()
pixelDeita () - 返回QPoint对象,为滚轮转过的像素值。
x() 和 y() - 返回相对于控件的当前鼠标的x,y位置;
pos() - 返回相对于控件的当前鼠标位置的QPoint对象;
posF() - 返回相对于控件的当前鼠标位置的QPoinFt对象;
globalX() 和globalY() - 返回相对于屏幕的当前鼠标的x,y位置;
globalPos() - 返回相对于屏幕的当前鼠标QPoint位置;
globalPosF() - 返回相对于屏幕的当前鼠标QPointF位置;
buttons(),modifiers()和timestamp()的用法参见本文“1.按下、松开鼠标按键”中的相关内容。
如果要让父控件继续收到滚轮事件,要调用事件的ignore()方法;否则,调用accept()。 -
更改鼠标指针形状
要修改鼠标进入控件后的形状,可调用QWidget的下列方法:
setCursor(QCursor qcr) - 参数qcr为QCursor对象或 Qtcore.Qt 类的枚举值,如:ArrowCursor(标准箭头)、upArrowCursor(向上箭头)、 CrossCursor(十字光标)、Waitcursor (沙漏),等等。setCursor(QtCore.Qt.WaitCursor)
unsetCursor() - 取消设置的鼠标形状。
cursor() - 返回当前鼠标形状的QCursor对象,。
使用QApplication类中的以下静态方法来控制整个应用程序的鼠标形状:setOverrideCursor(QCursor qcr) - 参数qcr为QCursor对象或 Qtcore.Qt 类的枚举值。
restoreOverrideCursor() - 取消全局鼠标形状设置;
changeOverrideCursor(QCursor qcr) - 将鼠标形状设置为qcr。只有先调用setOverrideCursor( )了,该函数才起作用。
overrideCursor( ) - 返回当前鼠标形状的QCursor 对象;
setOverrideCursor()和restoreOverrideCursor( )通常配合使用。
键盘事件
键盘事件笔者没有仔细看过,这里贴一片介绍的博客
建立信号跟槽通信
组件这边,添加信号跟槽
class WatchLabel(QtWidgets.QLabel):#自定义组件WatchLabel,继承自QLabel
def __init__(self,parent = None):
super(WatchLabel, self).__init__(parent)
WinShow = QtCore.pyqtSignal()#新建信号,到时候调用的方法就是WinShow,名字可以自己写
WinHide = QtCore.pyqtSignal()#新建信号
def enterEvent(self, *args, **kwargs):#定义鼠标移入事件,链接到WinShow信号
self.WinShow.emit()
def leaveEvent(self, *args, **kwargs):#定义鼠标移出事件,链接到WinHide信号
self.WinHide.emit()
调用的话,使用connect可以链接
#将WinShow与WinHide连接到函数上,注意这里函数BoxWinShow不是调用,是链接,所有没有(),写了会无法识别
self.label.WinShow.connect(self.BoxWinShow)
self.label.WinHide.connect(self.BoxWinHide)
#函数,显示弹窗窗口
def BoxWinShow(self):
self.boxWin = BoxWin()
self.boxWin.show()
#函数,隐藏弹窗窗口
def BoxWinHide(self):
self.boxWin = BoxWin()
self.boxWin.hide()
完整代码
两个文件
#MainWin.py
#主窗口文件,负责逻辑
import sys
from PyQt5.QtWidgets import QApplication,QMainWindow,QAction
from Ui_Form import *
class MainWin(QMainWindow,Win_Form):
def __init__(self,parent=None):
super(QMainWindow,self).__init__(parent)
self.setupUi(self)
#将WinShow与WinHide连接到函数上
self.label.WinShow.connect(self.BoxWinShow)
self.label.WinHide.connect(self.BoxWinHide)
def BoxWinShow(self):
self.boxWin = BoxWin()
self.boxWin.show()
def BoxWinHide(self):
self.boxWin = BoxWin()
self.boxWin.hide()
class BoxWin(QMainWindow,Box_Form):
def __init__(self,parent=None):
super(QMainWindow,self).__init__(parent)
self.setupUi(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWin()
win.show()
sys.exit(app.exec_())
#Ui_Form.py
#窗口Ui文件,负责控制样式QSS
from PyQt5 import QtCore, QtGui, QtWidgets
class WatchLabel(QtWidgets.QLabel):#自定义组件WatchLabel,继承自QLabel
def __init__(self,parent = None):
super(WatchLabel, self).__init__(parent)
WinShow = QtCore.pyqtSignal()#新建信号,到时候调用的方法就是WinShow,名字可以自己写
WinHide = QtCore.pyqtSignal()#新建信号
def enterEvent(self, *args, **kwargs):#定义鼠标移入事件,链接到WinShow信号
self.WinShow.emit()
def leaveEvent(self, *args, **kwargs):#定义鼠标移出事件,链接到WinHide信号
self.WinHide.emit()
class Win_Form(object):#主窗口UI格式
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(453, 327)
# 注意这里使用的是自定义的WatchLabel,而不是QtWidgets.QLabel,这样,这个Label就有了鼠标移入移出事件
self.label = WatchLabel(Form)
self.label.setGeometry(QtCore.QRect(20, 20, 161, 51))
self.label.setObjectName("label")
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.label.setText(_translate("Form", "这是一个组件,移入会有弹窗"))
class Box_Form(object):#弹窗窗口UI格式
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(354, 512)
Form.setMinimumSize(QtCore.QSize(354, 512))
Form.setMaximumSize(QtCore.QSize(354, 512))
self.label = QtWidgets.QLabel(Form)
self.label.setGeometry(QtCore.QRect(0, 0, 354, 512))
self.label.setMinimumSize(QtCore.QSize(354, 512))
self.label.setMaximumSize(QtCore.QSize(354, 512))
self.label.setText("")
self.label.setPixmap(QtGui.QPixmap("./弹窗.PNG"))
self.label.setObjectName("label")
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))