PyQt5信號與槽詳解


1、信號與槽函數基礎
'''
信號與槽函數基礎,信號是一個事件,發射信號之后槽函數就會執行
'''
from PyQt5.QtWidgets import *
import sys

class signal(QWidget):
def __init__(self):
super(signal,self).__init__()
self.initUI()

#編輯控件及其關聯的信號
def initUI(self):
self.resize(300,200)
self.setWindowTitle("信號與槽函數基礎")

self.b = QPushButton("我的按鈕",self) #利用第二個參數self直接可以顯示在窗口,不用布局來進行添加控件

#信號與槽函數連接
self.b.clicked.connect(self.onclick)

#編輯槽函數
def onclick(self):
self.b.setText("信號已經發出")
self.b.setStyleSheet("QPushButton(max-width:300px;min-width:300px)")

if __name__=="__main__":
app=QApplication(sys.argv)
p=signal()
p.show()
sys.exit(app.exec_())

2、自定義信號
'''
對於一個大類的對象,可以自定義實現一種信號
自定義信號的方式
pyqtSignal()信號對象
'''

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

#定義一個信號類
class MyTypesignal(QObject):

#定義一個信號
senmsg=pyqtSignal(object)
#編寫一個信號相關觸發的觸發函數
def run(self):
self.senmsg.emit("hello PyQT5") #通過run方法來發出message信息hello PyQt5

#定義一個槽函數類
class MySlot(QObject):
def get(self,msg):
print("信息:"+msg)

if __name__ == "__main__":
send=MyTypesignal()
slot=MySlot()

#將信號與槽函數連接
send.senmsg.connect(slot.get)
send.run()
#將信號與槽函數斷開
send.senmsg.disconnect(slot.get)
send.run()

3、發射多個參數的信號
'''
對於一個信號,可以設置通過一個觸發函數,發出多個參數
'''

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

#定義一個信號類
class MyTypesignal(QObject):

#定義一個信號
senmsg=pyqtSignal(object) #指定發出一個參數,類型為object對象
#發射3個參數的信號
senmsg1=pyqtSignal(str,int,int)

#編寫一個信號相關觸發的觸發函數
def run(self):
self.senmsg.emit("hello PyQT5") #通過run方法來發出message信息hello PyQt5

def run1(self):
self.senmsg1.emit("hello PyQT5",3,4) # 通過run方法來發出message信息hello PyQt5

#定義一個槽函數類
class MySlot(QObject):
def get(self,msg):
print("信息:"+msg)
def get1(self,msg,a,b):
print(msg,a,b)

if __name__ == "__main__":
send=MyTypesignal()
slot=MySlot()

#將信號與槽函數連接
send.senmsg.connect(slot.get)
send.senmsg1.connect(slot.get1)
send.run()
send.run1()
#將信號與槽函數斷開
send.senmsg.disconnect(slot.get)
send.senmsg1.disconnect(slot.get1)
send.run()
send.run1()

4、為類添加多個信號
'''
為一個類添加多個信號(重載形式信號)
對於一個重載多種形式的參數信號,觸發和關聯時都需要指定參數類型
'''

from PyQt5.QtCore import *
#定義一個信號類
class multisignal(QObject):

#定義一個信號
signal1=pyqtSignal()
#定義一個信號的傳入參數為int類型
signal2=pyqtSignal(int)

signal3=pyqtSignal(int,str)

signal4=pyqtSignal(list)

signal5=pyqtSignal(dict)

#申明一個重載版本的信號,也就是槽函數的參數可以是int和str類型,也可以只有一個str類型的信號
signal6=pyqtSignal([int,str],[str])

def __init__(self):
super(multisignal,self).__init__()

self.signal1.connect(self.signalcall1)
self.signal2.connect(self.signalcall2)
self.signal3.connect(self.signalcall3)
self.signal4.connect(self.signalcall4)
self.signal5.connect(self.signalcall5)

#關聯槽函數時需要指定傳入參數類型,對於多個發射參數形式的信號在了解時需要指定類型,不然默認第一種情況
self.signal6[int,str].connect(self.signalcall6)
self.signal6[str].connect(self.signalcall6overload)

self.signal1.emit()
self.signal2.emit(10)
self.signal3.emit(1,"hello")
self.signal4.emit([1,2,3,4])
self.signal5.emit({"name":"燕江依","sex":"male"})

#發出參數時也需要指定信號的參數類型,默認關聯到第一種類型上去,也就是int+str類型
self.signal6[int,str].emit(20,"test")
self.signal6[str].emit("text")

def signalcall1(self):
print("signal1 emit")
def signalcall2(self,val):
print("signal2 emit,value:",val)
def signalcall3(self,val,text):
print("signal3 emit",val,text)
def signalcall4(self, val):
print("signal4 emit,value:", val)
def signalcall5(self,val):
print("signal6 emit",val)
def signalcall6(self, val,text):
print("signal6 emit,value:", val,text)
def signalcall6overload(self, val):
print("signal6 overload emit,value:", val)

if __name__ == "__main__":
mul=multisignal()

5、多線程更新UI數據(利用信號與槽函數在兩個線程之間傳遞數據)
from PyQt5.QtCore import QThread,pyqtSignal,QDateTime
from PyQt5.QtWidgets import QApplication,QDialog,QLineEdit
import time
import sys

#定義一個動態顯示當前時間的線程類
class back(QThread):
update_date=pyqtSignal(str)
def run(self):
while True:
date=QDateTime.currentDateTime()
current=date.toString("yyyy-MM-dd hh:mm:ss")
self.update_date.emit(str(current))
time.sleep(1)

#定義一個主窗口
class threadupdate(QDialog):
def __init__(self):
QDialog.__init__(self)
self.setWindowTitle("多線程更新UI數據")
self.resize(400,100)
self.input=QLineEdit(self)
self.input.resize(400,100)
self.initUI()

def initUI(self):
self.backend=back()
self.backend.update_date.connect(self.handledisplay)
self.backend.start() #啟動線程程序

def handledisplay(self,data):
self.input.setText(data)

if __name__=="__main__":
app=QApplication(sys.argv)
p=threadupdate()
p.show()
sys.exit(app.exec_())

6、信號與槽函數實現自動連接
'''
實現的方法詳解如下:
1、定義控件的名稱,設置控件與信號連接的原則,以名稱自動連接
self.button.setObjectName("objectname")
QtCore.QMetaObject.connectSlotsByName(self)
2、槽函數格式為:
@QtCore.pyqtSlot()
def on_objectname_signalname(self):
3、參數說明
(1)objectname必須和關聯控件名稱一致
(2)signalname必須和控件所需要關聯的信號名稱一致
'''

from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication,QWidget,QHBoxLayout,QPushButton
import sys

class autosignalslot(QWidget):
def __init__(self):
super(autosignalslot,self).__init__()
self.ok=QPushButton("OK",self)

#第一步設置關聯信號控件按鈕的名字
self.ok.setObjectName("okbutton")
self.cancle = QPushButton("cancel",self)
self.cancle.setObjectName("canclebutton")

#第二步:設置信號與控件連接的原則
QtCore.QMetaObject.connectSlotsByName(self)

layout = QHBoxLayout()
layout.addWidget(self.ok)
layout.addWidget(self.cancle)
self.setLayout(layout)

#使用手動定義關聯關系來進行信號與槽函數的匹配
#self.ok.clicked.connect(self.on_okbutton)

#第三步:定義槽函數:采用自動信號與槽函數之間的關聯
@QtCore.pyqtSlot()
def on_okbutton_clicked(self):
print("點擊了ok按鈕")

@QtCore.pyqtSlot()
def on_canclebutton_clicked(self):
print("點擊了cancle按鈕")

if __name__=="__main__":
app=QApplication(sys.argv)
p=autosignalslot()
p.show()
sys.exit(app.exec_())

7、信號與槽函數連接與斷開N對N連接
'''
1.一個信號關聯多個槽函數
2.一個槽函數可以被多個信號關聯
3.一個信號可以關聯另外一個信號可以實現觸發另外一個信號
'''
from PyQt5.QtCore import *

class NNsignal(QObject):
signal1=pyqtSignal()
signal2=pyqtSignal(int)
signal3=pyqtSignal(int)

def __init__(self):
super(NNsignal,self).__init__()
#一個信號關聯多個槽函數
self.signal1.connect(self.call1)
self.signal1.connect(self.call2)
self.signal2.connect(self.call3)

#信號2觸發信號3,信號關聯信號,需要注意信號傳入參數的一致性,不然觸發不了
self.signal2.connect(self.signal3) #信號2和信號3關聯,直接會觸發信號3關聯的槽函數
#一個槽函數被多個信號關聯
self.signal3.connect(self.call3)

self.signal1.emit() #一個信號觸發多個槽函數
self.signal2.emit(100)
self.signal2.emit(2)

def call1(self):
print("call1 emit")
def call2(self):
print("call2 emit")
def call3(self,int):
print("call3 emit",int)

if __name__ == "__main__":
mul=NNsignal()

8、為窗口添加關閉窗口信號

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys

class winsignal(QWidget):
buttonsignal=pyqtSignal()

def __init__(self):
super(winsignal,self).__init__()
self.setWindowTitle("為窗口類添加窗口關閉信號")
self.resize(300,100)

b=QPushButton("關閉窗口",self)
b.clicked.connect(self.b_click)
self.buttonsignal.connect(self.b_close)
def b_click(self):
self.buttonsignal.emit()
def b_close(self):
self.close()
if __name__=="__main__":
app=QApplication(sys.argv)
p=winsignal()
p.show()
sys.exit(app.exec_())

9、lambda表達式為槽函數傳遞參數
'''
python中的lambda表達式:沒有名字的函數:即匿名函數
'''
#不帶參數的函數定義
fun=lambda :print("hello world")
fun()
#帶參數函數的定義
f=lambda x,y:x*y**2
print(f(3,4))

from PyQt5.QtWidgets import *
import sys
class lambdaslot(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("使用lambda表達式為槽函數傳遞參數")

self.b1=QPushButton("按鈕1")
self.b2=QPushButton("按鈕2")

#相當於click點擊信號+lamda表達式便可以實現點擊傳入槽函數參數
self.b1.clicked.connect(lambda: self.onbutton(10, 20))
self.b2.clicked.connect(lambda: self.onbutton(10, -20))
self.b1.clicked.connect(lambda :QMessageBox.information(self,"結果","單擊了button1"))

lay=QHBoxLayout()
lay.addWidget(self.b1)
lay.addWidget(self.b2)

m=QWidget()
m.setLayout(lay)
self.setCentralWidget(m)
#槽函數需要參數,而button點擊不能傳入參數,可以使用lambda表達式傳入參數
def onbutton(self,m,n):
print("m+n=",m+n)
QMessageBox.information(self,"結果",str(m+n))

if __name__ == "__main__":
app = QApplication(sys.argv)
p =lambdaslot()
p.show()
sys.exit(app.exec_())

10、partial對象為槽函數傳遞參數
'''
python中的lpartial對象
partial(f,參數1,參數2,...)
'''

from PyQt5.QtWidgets import *
import sys
from functools import partial

class partialslot(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("使用partial對象為槽函數傳遞參數")

self.b1=QPushButton("按鈕1")
self.b2=QPushButton("按鈕2")

#相當於click點擊信號+lamda表達式便可以實現點擊傳入槽函數參數
self.b1.clicked.connect(partial(self.onbutton,10,20))
self.b2.clicked.connect(partial(self.onbutton,20,-40))

lay=QHBoxLayout()
lay.addWidget(self.b1)
lay.addWidget(self.b2)

m=QWidget()
m.setLayout(lay)
self.setCentralWidget(m)

#槽函數需要參數,而button點擊不能傳入參數,可以使用partial對象傳入參數
def onbutton(self,m,n):
print("m+n=",m+n)
QMessageBox.information(self,"結果",str(m+n))

if __name__ == "__main__":
app = QApplication(sys.argv)
p =partialslot()
p.show()
sys.exit(app.exec_())

11、覆蓋槽函數(鍵盤按鍵信號連接自定義槽函數)
'''
覆蓋槽函數
'''

from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
import sys

#按鍵信號與槽函數進行關聯,自定義屬性
class overrideslot(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("覆蓋槽函數")

#系統里面的按鍵槽函數與信號連接,可以自定義槽函數里面的功能
def keyPressEvent(self, e):
if e.key()==Qt.Key_Escape:
self.close()
elif e.key()==Qt.Key_Alt:
self.setWindowTitle("按下了ALT鍵")

if __name__ == "__main__":
app = QApplication(sys.argv)
p =overrideslot()
p.show()
sys.exit(app.exec_())







免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM