槽和信号
信号和槽
'''
信号(Signal)与槽(Slot)
'''
from PyQt5.QtWidgets import *
import sys
class SigalSlotDemo(QWidget):
def __init__(self):
super(SigalSlotDemo,self).__init__()
self.initUI()
def onClick(self):
self.btn.setText("信号已经发出")
self.btn.setStyleSheet("QPushButton(max-width:200px;min-width:200px")
def initUI(self):
self.setGeometry(300, 300, 500, 400)
self.setWindowTitle('信号(Signal)与槽(Slot)')
self.btn = QPushButton('我的按钮',self)
self.btn.clicked.connect(self.onClick)
if __name__ == '__main__':
app = QApplication(sys.argv)
gui = SigalSlotDemo()
gui.show()
sys.exit(app.exec_())
自定义信号
'''
自定义信号
pyqtSignal()
'''
from PyQt5.QtCore import *
class MyTypeSignal(QObject):
# 定义一个信号
sendmsg = pyqtSignal(object)
# 发送3个参数的信号
sendmsg1 = pyqtSignal(str,int,int)
def run(self):
self.sendmsg.emit('Hello PyQt5')
def run1(self):
self.sendmsg1.emit("hello",3,4)
class MySlot(QObject):
def get(self,msg):
print("信息:" + msg)
def get1(self,msg,a,b):
print(msg)
print(a+b)
if __name__ == '__main__':
send = MyTypeSignal()
slot = MySlot()
send.sendmsg.connect(slot.get)
send.sendmsg1.connect(slot.get1)
send.run()
send.run1()
send.sendmsg.disconnect(slot.get)
send.run()为类添加多个信号
'''
为类添加多个信号
'''
from PyQt5.QtCore import *
class MultiSignal(QObject):
signal1 = pyqtSignal()
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[str].connect(self.signalCall6Overload)
self.signal6[int,str].connect(self.signalCall6)
self.signal1.emit()
self.signal2.emit(10)
self.signal3.emit(1,"hello world")
self.signal4.emit([1,2,3,4,5,6])
self.signal5.emit({"name":"Bill","age":30})
self.signal6[str].emit("test")
self.signal6[int,str].emit(100,"mytest")
def signalCall1(self):
print("signal1 emit")
def signalCall2(self,val):
print("signal2 emit,value:", val)
def signalCall3(self,val,text):
print("signal3 emit,value:", val,text)
def signalCall4(self,val):
print("signal4 emit,value:", val)
def signalCall5(self,val):
print("signal5 emit,value:", 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__':
multiSignal = MultiSignal()信号槽N对N连接与断开连接
'''
信号槽N对N连接与断开连接
'''
from PyQt5.QtCore import *
class NNSignal(QObject):
signal1 = pyqtSignal()
signal2 = pyqtSignal(int)
signal3 = pyqtSignal()
def __init__(self):
super(NNSignal,self).__init__()
self.signal1.connect(self.call1)
self.signal1.connect(self.call11)
self.signal3.connect(self.call1)
self.signal1.emit()
self.signal3.emit()
'''
self.signal2.connect(self.signal1)
self.signal2.emit(2) # 触发了信号1
self.signal1.disconnect(self.call1)
self.signal1.disconnect(self.call11)
self.signal2.disconnect(self.signal1)
self.signal1.connect(self.call1)
self.signal2.connect(self.call2)
self.signal1.emit()
self.signal2.emit(100)
'''
def call1(self):
print("call1 emit")
def call11(self):
print("call11 emit")
def call2(self,val):
print("call2 emit:",val)
if __name__ == '__main__':
nnSignal = NNSignal()
为窗口类添加信号
'''
为窗口类添加信号
'''
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
class WinSignal(QWidget):
button_clicked_signal = pyqtSignal()
def __init__(self):
super().__init__()
self.setWindowTitle("为窗口类添加信号")
self.resize(300,100)
btn = QPushButton('关闭窗口',self)
btn.clicked.connect(self.btn_clicked)
self.button_clicked_signal.connect(self.btn_close)
def btn_clicked(self):
self.button_clicked_signal.emit()
def btn_close(self):
self.close()
if __name__ == '__main__':
app = QApplication(sys.argv)
example = WinSignal()
example.show()
sys.exit(app.exec_())多线程更新UI数据
'''
多线程更新UI数据(在两个线程中传递数据)
'''
from PyQt5.QtCore import QThread , pyqtSignal, QDateTime
from PyQt5.QtWidgets import QApplication, QDialog, QLineEdit
import time
import sys
class BackendThread(QThread):
update_date = pyqtSignal(str)
def run(self):
while True:
data = QDateTime.currentDateTime()
currentTime = data.toString("yyyy-MM-dd hh:mm:ss")
self.update_date.emit(str(currentTime))
time.sleep(1)
class ThreadUpdateUI(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 = BackendThread()
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)
example = ThreadUpdateUI()
example.show()
sys.exit(app.exec_())信号与槽的自动连接
'''
信号与槽自动连接
on_objectname_signalname
on_okButton_clicked
'''
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.okButton = QPushButton("ok",self)
self.okButton.setObjectName("okButton")
self.okButton1 = QPushButton("cancel",self)
self.okButton1.setObjectName("cancelButton")
layout = QHBoxLayout()
layout.addWidget(self.okButton)
self.setLayout(layout)
QtCore.QMetaObject.connectSlotsByName(self)
#self.okButton.clicked.connect(self.on_okButton_clicked)
@QtCore.pyqtSlot()
def on_okButton_clicked(self):
print("点击了ok按钮")
@QtCore.pyqtSlot()
def on_cancelButton_clicked(self):
print("点击了cancel按钮")
if __name__ == '__main__':
app = QApplication(sys.argv)
example = AutoSignalSlot()
example.show()
sys.exit(app.exec_())使用Lambda表达式为槽函数传递参数
'''
使用Lambda表达式为槽函数传递参数
Lambda表达式:匿名函数,也就是没有名字的函数
fun = lambda :print("hello world")
fun()
fun1 = lambda x,y:print(x,y)
fun1("a","b")
'''
from PyQt5.QtWidgets import *
import sys
class LambdaSlotArg(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("使用Lambda表达式为槽函数传递参数")
button1 = QPushButton("按钮1")
button2 = QPushButton("按钮2")
ok = 100
button1.clicked.connect(lambda :self.onButtonClick(10,ok))
button2.clicked.connect(lambda :self.onButtonClick(ok,-20))
button1.clicked.connect(lambda :QMessageBox.information(self,"结果","单击了button1"))
layout = QHBoxLayout()
layout.addWidget(button1)
layout.addWidget(button2)
mainFrame = QWidget()
mainFrame.setLayout(layout)
self.setCentralWidget(mainFrame)
def onButtonClick(self,m,n):
print("m + n =",m + n )
QMessageBox.information(self,"结果",str(m+n))
if __name__ == "__main__":
app = QApplication(sys.argv)
form = LambdaSlotArg()
form.show()
sys.exit(app.exec_())使用Partial对象为槽函数传递参数
'''
使用Partial对象为槽函数传递参数
'''
from PyQt5.QtWidgets import *
import sys
from functools import partial
class PartialSlotArg(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("使用Partial表达式为槽函数传递参数")
button1 = QPushButton("按钮1")
button2 = QPushButton("按钮2")
x = 20
y = -123
button1.clicked.connect(partial(self.onButtonClick,10,20))
button2.clicked.connect(partial(self.onButtonClick, x, y))
layout = QHBoxLayout()
layout.addWidget(button1)
layout.addWidget(button2)
mainFrame = QWidget()
mainFrame.setLayout(layout)
self.setCentralWidget(mainFrame)
def onButtonClick(self,m,n):
print("m + n =",m + n )
QMessageBox.information(self,"结果",str(m+n))
if __name__ == "__main__":
app = QApplication(sys.argv)
form = PartialSlotArg()
form.show()
sys.exit(app.exec_())Override(覆盖)槽函数
'''
Override(覆盖)槽函数
'''
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
class OverrideSlot(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Override(覆盖)槽函数")
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)
form = OverrideSlot()
form.show()
sys.exit(app.exec_())多窗口交互
'''
多窗口交互(1):不使用信号与槽
Win1
Win2
'''
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from DateDialog import DateDialog
class MultiWindow1(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("多窗口交互(1):不使用信号与槽")
self.lineEdit = QLineEdit(self)
self.button1 = QPushButton('弹出对话框1')
self.button1.clicked.connect(self.onButton1Click)
self.button2 = QPushButton('弹出对话框2')
self.button2.clicked.connect(self.onButton2Click)
gridLayout = QGridLayout()
gridLayout.addWidget(self.lineEdit)
gridLayout.addWidget(self.button1)
gridLayout.addWidget(self.button2)
self.setLayout(gridLayout)
def onButton1Click(self):
dialog = DateDialog(self)
result = dialog.exec()
date = dialog.dateTime()
self.lineEdit.setText(date.date().toString())
dialog.destroy()
def onButton2Click(self):
date,time,result = DateDialog.getDateTime()
self.lineEdit.setText(date.toString())
if result == QDialog.Accepted:
print('点击确定按钮')
else:
print('单击取消按钮')
if __name__ == "__main__":
app = QApplication(sys.argv)
form = MultiWindow1()
form.show()
sys.exit(app.exec_())
多窗口交互(2):使用信号与槽
'''
多窗口交互(2):使用信号与槽
如果一个窗口A与另一个窗口B交互,那么A尽量不要直接访问B窗口中的控件,
应该访问B窗口中的信号,并指定与信号绑定的槽函数
例:如果A直接访问B窗口的控件,一旦B窗口控件发生改变,那么A和B的代码都需要变化
如果A访问的是B中的信号,那么B中的控件发生了改变,只需要修改B中的代码即可
'''
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from NewDateDialog import NewDateDialog
class MultiWindow2(QWidget):
def __init__(self, parent=None):
super(MultiWindow2, self).__init__(parent)
self.resize(400, 90)
self.setWindowTitle('多窗口交互(2):使用信号与槽')
self.open_btn = QPushButton('获取时间')
self.lineEdit_inner = QLineEdit(self)
self.lineEdit_emit = QLineEdit(self)
self.open_btn.clicked.connect(self.openDialog)
self.lineEdit_inner.setText('接收子窗口内置信号的时间')
self.lineEdit_emit.setText('接收子窗口自定义信号的时间')
grid = QGridLayout()
grid.addWidget(self.lineEdit_inner)
grid.addWidget(self.lineEdit_emit)
grid.addWidget(self.open_btn)
self.setLayout(grid)
def openDialog(self):
dialog = NewDateDialog(self)
# 连接子窗口的内置信号与主窗口的槽函数
dialog.datetime_inner.dateTimeChanged.connect(self.deal_inner_slot)
# 连接子窗口的自定义信号与主窗口的槽函数
dialog.Signal_OneParameter.connect(self.deal_emit_slot)
dialog.show()
def deal_inner_slot(self, date):
self.lineEdit_inner.setText(date.toString())
def deal_emit_slot(self, dateStr):
self.lineEdit_emit.setText(dateStr)
if __name__ == "__main__":
app = QApplication(sys.argv)
form = MultiWindow2()
form.show()
sys.exit(app.exec_())
DateDialog.py
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class DateDialog(QDialog):
def __init__(self,parent=None):
super(DateDialog,self).__init__(parent)
self.setWindowTitle("DateDialog")
layout = QVBoxLayout(self)
self.datetime = QDateTimeEdit(self)
self.datetime.setCalendarPopup(True)
self.datetime.setDateTime(QDateTime.currentDateTime())
layout.addWidget(self.datetime)
buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel,Qt.Horizontal,self)
buttons.accepted.connect(self.accept)
buttons.rejected.connect(self.reject)
layout.addWidget(buttons)
def dateTime(self):
return self.datetime.dateTime()
@staticmethod
def getDateTime(parent = None):
dialog = DateDialog(parent)
result = dialog.exec()
date = dialog.dateTime()
return (date.date(),date.time(),result == QDialog.Accepted)
NewDateDialog.py
from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class NewDateDialog(QDialog): Signal_OneParameter = pyqtSignal(str) def __init__(self, parent=None): super(NewDateDialog, self).__init__(parent) self.setWindowTitle('子窗口:用来发射信号') # 在布局中添加部件 layout = QVBoxLayout(self) self.label = QLabel(self) self.label.setText('前者发射内置信号\n后者发射自定义信号') self.datetime_inner = QDateTimeEdit(self) self.datetime_inner.setCalendarPopup(True) self.datetime_inner.setDateTime(QDateTime.currentDateTime()) self.datetime_emit = QDateTimeEdit(self) self.datetime_emit.setCalendarPopup(True) self.datetime_emit.setDateTime(QDateTime.currentDateTime()) layout.addWidget(self.label) layout.addWidget(self.datetime_inner) layout.addWidget(self.datetime_emit) # 使用两个button(ok和cancel)分别连接accept()和reject()槽函数 buttons = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) layout.addWidget(buttons) self.datetime_emit.dateTimeChanged.connect(self.emit_signal) def emit_signal(self): date_str = self.datetime_emit.dateTime().toString() self.Signal_OneParameter.emit(date_str)
天道酬勤 循序渐进 技压群雄










浙公网安备 33010602011771号