0%

PyQt5信号槽机制(一)

PyQt5信号槽机制(一)

信号槽是Qt的核心机制,也是PyQt中编程的通信机制,在Qt中,QObject对象和PyQt中所有继承自QWidget的控件都支持信号机制。当信号发射时,连接的槽函数会自动执行。在PyQt5中,信号和槽函数通过object.signal.connect()方法进行连接。

信号槽(slot)简介

信号槽特点如下:

  1. 一个信号可以连接多个槽
  2. 一个信号可以连接另一个信号
  3. 信号参数可以是任意Python类型
  4. 一个槽可以监听任意多个信号
  5. 信号与槽之间的连接方式可以是同步连接,也可以是异步连接
  6. 信号与槽的连接可以跨线程
  7. 信号可以断开
    在编写一个类的时候,要首先定义类的信号和槽,在类的信号与槽进行连接,实现对象之间的数据传输。当事件或状态发生改变时,会发出信号,进而出发执行事件或信号相关联的槽函数
    槽信号

定义信号

PyQt内置信号是自动定义的,使用PyQt5.QtCore.pyqtSignal函数可以为QObject对象创建一个信号,使用pyqtSignal函数可以把信号定义为类的属性。pyqtSignal的原型如下

1
2
class pyqtSignal:
def __init__(self, *types, name: str= ...) -> None: ...

  • type:表示定义信号时参数的类型
  • name:表示信号的名称,默认使用类的属性名称
    使用pyqtSignal函数创建一个或多个重载的未绑定的信号作为类的属性,信号只能在QObject的子类中定义。信号必须在类创建时定义,不能在类创建后作为类的属性动态添加进来。使用pyqtSignal函数定义信号时,信号可以传递多各参数,并指定信号传递参数的类型,参数类型是标准的Python数据类型,包括字符串、日期、布尔类型、数字、列表、字典、元组
1
2
3
4
5
6
7
8
from PyQt5.QtCore import pyqtSignal, QObject

class StandardItem(QObject):
data_changed = pyqtSignal(str, str, name='dataChanged')

def update(self):
self.dataChanged.emit("old status","new status")

操作信号

  • connect函数:将信号绑定到槽函数上,QObject.signal.connect(self, slot, type=None, no_receiver_check=False)
  • disconnect函数:将信号解绑,QObject.signal.disconnect(self, slot=None)
  • emit函数:发射信号,emit(self, *args)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from PyQt5.QtCore import pyqtSignal, QObject

class StandardItem(QObject):
data_changed = pyqtSignal(str, str, name='dataChanged')

def update(self):
self.dataChanged.emit("old status","new status")

# 槽函数
def onDataChanged(self, old, new):
print(old)
print(new)

if __name__ == '__main__':
app = QCoreApplication(sys.argv)
item = StandardItem()
item.dataChanged.connect(item.onDataChanged)
item.update()

sys.exit(app.exec_())

###############
#####OUTPUT####
###############
# old status
# new status

信号槽与应用

内置信号与自定义槽函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import sys
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton


class MainWindow(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("MainWindow Demo")
self.resize(800, 600)

button = QPushButton("close", self)
# 连接内置信号与自定义槽
button.clicked.connect(self.onClose)

# 自定义槽函数
def onClose(self):
self.close()


if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()

sys.exit(app.exec_())

这里,button.click()就是一个内置信号,他与onClose槽函数连接。而用户按下的动作即为发射。点击按钮时触发按钮内置的clicked信号,执行绑定的自定义槽函数onClose。

自定义信号和内置槽函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import sys
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton


class MainWindow(QWidget):
closeSignal = pyqtSignal()

def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("MainWindow Demo")
self.resize(800, 600)

button = QPushButton("close", self)
# 连接内置信号与自定义槽
button.clicked.connect(self.onClose)
# 连接自定义信号closeSignal与内置槽函数close
self.closeSignal.connect(self.close)

# 自定义槽函数
def onClose(self):
# 发送自定义信号
self.closeSignal.emit()


if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()

sys.exit(app.exec_())

通过内置信号click连接到自定义槽函数,槽函数中触发自定义信号的发射,从而触发内置槽函数QWidget.close()函数

自定义信号和自定义槽函数

结合上述两种方法,大同小异

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import sys
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton


class MainWindow(QWidget):
closeSignal = pyqtSignal()

def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("MainWindow Demo")
self.resize(800, 600)

button = QPushButton("close", self)
# 连接内置信号与自定义槽
button.clicked.connect(self.onClicked)
# 连接自定义信号closeSignal与内置槽函数close
self.closeSignal.connect(self.onClose)

# 自定义槽函数
def onClicked(self):
# 发送自定义信号
self.closeSignal.emit()

# 自定义槽函数
def onClose(self):
self.close()


if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()

sys.exit(app.exec_())

参考自:
PyQt5快速入门(二)PyQt5信号槽机制