【PyQt5】信號與槽用法進階


4.高級自定義信號與槽

  自定義信號與槽是PyQt5必須掌握的核心玩法,只有4個步驟:

  定義信號 --> 定義槽函數 --> 連接 --> 發射

  在使用面向對象方式寫代碼的時候從上往下的順序最有可能的是:

  定義信號 --> 連接 --> 發射 --> 定義槽函數 

  4.1  定義信號 

  信號可以帶任何形式的參數。

    signal1 = pyqtSignal()  # 無參數
    signal2 = pyqtSignal(int)  # 1個字符串參數
    signal3 = pyqtSignal(int, str) # 2個不同類型參數,數字和字符串,當然一樣類型的也是可以的
    signal4 = pyqtSignal(list) # 列表
    signal5 = pyqtSignal(dict) # 字典
    signal6 = pyqtSignal([int, str], [str]) # 可以重載的不同類型及不同個數的參數

  看到這里,“重載”這個概念不是很好理解,但是只要看了下面的例子基本可以懂。我的理解就是把signal3和signal2組成了一個信號字典(這只能用來理解,但內部原理不一定是這樣),具有可以重載的參數的信號調用方式如下:

        self.signal6[int, str].connect(self.signal_call_6)
        self.signal6[str].connect(self.signal_call_6_overload)

    #是不是有點像下面的形式:
    signal6 = {
        'int, str':signal3,
        'str':signal2,
        }

  4.2  定義槽函數

  沒有難點,就是需要注意,信號帶的參數的個數和類型要與定義的槽函數的變量保持一致這里有一個知識點是【有些無參的自定義信號怎么帶參數的問題】,放到最后來添加一個案例【4.6 參數不一致的處理方法】解釋。

    4.3  連接信號與槽

  使用 .connect()

  4.4  發射信號

  signal.emit(參數)

  4.5 完整案例

from PyQt5.QtCore import QObject, pyqtSignal


class CustSignal(QObject):
#1.定義信號 signal1
= pyqtSignal() # 無參數 signal2 = pyqtSignal(int) # 1個字符串參數 signal3 = pyqtSignal(int, str) # 2個不同類型參數,數字和字符串,當然一樣類型的也是可以的 signal4 = pyqtSignal(list) # 列表 signal5 = pyqtSignal(dict) # 字典 signal6 = pyqtSignal([int, str], [str]) # 可以重載的不同類型及不同個數的參數 def __init__(self, parent=None): super(CustSignal, self).__init__(parent) #2.連接 self.signal1.connect(self.signal_call_1) self.signal2.connect(self.signal_call_2) self.signal3.connect(self.signal_call_3) self.signal4.connect(self.signal_call_4) self.signal5.connect(self.signal_call_5) self.signal6[int, str].connect(self.signal_call_6) self.signal6[str].connect(self.signal_call_6_overload) #3.發射 self.signal1.emit() self.signal2.emit(1) self.signal3.emit(1,'haha') self.signal4.emit([1,2,3]) self.signal5.emit({'text':'balabala'}) self.signal6[int, str].emit(1,'text') self.signal6[str].emit('text') #4.定義槽函數 def signal_call_1(self): print('signal1 emit') def signal_call_2(self,val): print('signal2 emit',val) def signal_call_3(self, val, text): print('signal3 emit', val, text) def signal_call_4(self, list): print('signal14 emit', list) def signal_call_5(self, dict): print('signal5 emit',dict) def signal_call_6(self, v, t): print('signal6 emit', v, t) def signal_call_6_overload(self, t): print('signal6 emit', t) if __name__ == '__main__': cust = CustSignal()

  運行后的結果是:

signal1 emit
signal2 emit 1
signal3 emit 1 haha
signal4 emit [1, 2, 3]
signal5 emit {'text': 'balabala'}
signal6 emit 1 text
signal6 emit text

  4.6 參數不一致的處理方法

使用lambda函數

import sys
from PyQt5.QtWidgets import QMainWindow, QPushButton, QWidget,QMessageBox, QApplication,QHBoxLayout

class win_form(QMainWindow):
    def __init__(self,parent=None):
        super(win_form, self).__init__(parent)
        btn1 = QPushButton('btn1')
        btn2 = QPushButton('btn2')

        btn1.clicked.connect(lambda :self.btn_click(1))
        btn2.clicked.connect(lambda :self.btn_click(2))

        layout = QHBoxLayout()
        layout.addWidget(btn1)
        layout.addWidget(btn2)

        main_frame = QWidget()
        main_frame.setLayout(layout)

        self.setCentralWidget(main_frame)

    def btn_click(self, n):
        # print('btn %d 被按下'%n)
        QMessageBox.information(self,'結果提示框','btn %d 被按下'%n)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    form = win_form()
    form.show()
    sys.exit(app.exec_())

  書上的這個例子很清楚,但是如果再定義一個槽函數接收.clicked的參數,會發現一個很有意思的事情。比如:

btn1.clicked.connect(self.btn1_slot)
def btn1_slot(self,n):
    print(n)

結果會是這樣:

False

那是不是說 .clicked是發出了1個參數的,參數是bool值。導航到clicked函數,果然:

    def clicked(self, checked=False): # real signature unknown; restored from __doc__
        """ clicked(self, checked: bool = False) [signal] """
        pass

接着看下面的,如果我再連接一個槽函數:

btn1.clicked.connect(self.btn_click) # 不用lanbda調用

點擊btn1,結果又是這樣:

0!是怎么來的!!?

0!是怎么來的!!?

0!是怎么來的!!?


免責聲明!

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



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