java 信号 槽,【PyQt5】信号与槽用法进阶(示例代码)

  • Post author:
  • Post category:java


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 importQObject, pyqtSignalclassCustSignal(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.定义槽函数defsignal_call_1(self):print(‘signal1 emit‘)defsignal_call_2(self,val):print(‘signal2 emit‘,val)defsignal_call_3(self, val, text):print(‘signal3 emit‘, val, text)defsignal_call_4(self, list):print(‘signal14 emit‘, list)defsignal_call_5(self, dict):print(‘signal5 emit‘,dict)defsignal_call_6(self, v, t):print(‘signal6 emit‘, v, t)defsignal_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函数

importsysfrom PyQt5.QtWidgets importQMainWindow, QPushButton, QWidget,QMessageBox, QApplication,QHBoxLayoutclasswin_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)defbtn_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)defbtn1_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,结果又是这样:

20200210174031997064.png

0!是怎么来的!!?

0!是怎么来的!!?

0!是怎么来的!!?