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"))