• 槽和信号


    信号和槽

    '''
    
    信号(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-200px;min-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_())
    image

    自定义信号

    '''
    
    自定义信号
    
    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()

    image

    为类添加多个信号
    '''
    为类添加多个信号
    
    '''
    
    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()
    image
    信号槽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()
    image
    为窗口类添加信号
    '''
    
    为窗口类添加信号
    
    '''
    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_())
    image
    多线程更新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_())
    image
    信号与槽的自动连接
    '''
    信号与槽自动连接
    
    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_())
    image
    使用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_())
    image
    使用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_())
    image
    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_())
    image
    多窗口交互
    '''
    
    多窗口交互(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_())
    
    image
    多窗口交互(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_())
    
    image
    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('前者发射内置信号
    后者发射自定义信号')
    
            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)
    
    
    

    天道酬勤 循序渐进 技压群雄
  • 相关阅读:
    Python 生成器相关知识
    openpyxl 模块学习记录
    Python 装饰器相关知识
    Python 闭包的相关知识
    Python 内置函数简单介绍
    Git提交的本地仓库在什么位置
    支付宝公钥,私钥加密解密问题
    字符转义
    pyhton 模拟浏览器实现
    大小端模式 大端存储 小端存储
  • 原文地址:https://www.cnblogs.com/wuyuan2011woaini/p/14832058.html
Copyright © 2020-2023  润新知