PyQt5 一信号多槽
PyQt5 one signal and multiple slots
我在下面提出了一个简单的 signal/slot 机制。当通过 QSlider::valueChanged() 更改值时,QSlider 会调用该信号。插槽通过 QLCDNumber::display() 方法调用。
令我困惑的是为什么 PyQt5 的文档如此之少,而大多数文档都指向 Qt5 的链接。我对代码的具体问题是:
1) 如果QSlider::valueChanged() (signal) expects an integer as a parameter why do we only pass in QLCDNumber::display() (slot) 是void函数。因此,不会传入任何内容。
2) 在下面注释掉的代码中,我无法调用第二个插槽。 1 个信号可以调用的插槽数量是否有限制?如果有我如何去调用 PyQt5 中的多个插槽。
编辑:我相信是因为 printLabel() 不是定义的插槽,这就是我遇到问题的原因。我可以在 ::connect() 参数中包含任意数量的插槽吗?或者我是不是以一种 hacky 的方式来处理这个问题。
import sys
from PyQt5.QtCore import (Qt)
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def printLabel(self, str):
print(str)
def initUI(self):
lcd = QLCDNumber(self)
sld = QSlider(Qt.Horizontal, self)
vbox = QVBoxLayout()
vbox.addWidget(lcd)
vbox.addWidget(sld)
self.setLayout(vbox)
#This line works
sld.valueChanged.connect(lcd.display)
#This line does not work
#sld.valueChanged.connect(lcd.display, self.printLabel("hi"))
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
整理你的观点:
Qt5 文档包含至少 90% 的您需要了解的内容,因此在 PyQt5 文档中重复所有内容毫无意义,它主要集中在 PyQt 特有的功能上(例如,参见 Signals and Slots 文章)。 Qt5 是一个 C++ 库。您无需了解 C++ 即可使用 PyQt(或阅读 Qt 的优秀文档),但您很难期望完全避免使用它。
QSlider.valueChanged
信号 发送 一个 int 值到所有连接到它的插槽。 QLCDNUmber.display
插槽 接收 字符串、整数或浮点对象(即它具有三个重载)。对于内置的 Qt 槽,必须有一个与信号发送相匹配的重载。但是PyQt中自定义槽可以是any python可调用对象,签名不匹配也没关系(任何多余的参数都会被丢弃) .话虽如此,可以通过使用 pyqtSlot
装饰器为用户定义的插槽定义显式签名 (因此允许在 PyQt 中指定多个重载)。
正如上面提到的PyQt文章第一节所解释的,信号和槽都可以有多个连接。文章还详细介绍了 PyQt 特定的 API(包括 pyqtSlot
),并给出了如何使用它们的示例。
以下是连接到多个插槽的示例:
class Example(QWidget):
...
def initUI(self):
...
#connect to a built-in slot
sld.valueChanged.connect(lcd.display)
#connect to a user-defined lot
sld.valueChanged.connect(self.printLabel)
#any python callable will do
sld.valueChanged.connect(lambda x: print('lambda:', x))
...
def printLabel(self, value):
print('printLabel:', value)
我在下面提出了一个简单的 signal/slot 机制。当通过 QSlider::valueChanged() 更改值时,QSlider 会调用该信号。插槽通过 QLCDNumber::display() 方法调用。
令我困惑的是为什么 PyQt5 的文档如此之少,而大多数文档都指向 Qt5 的链接。我对代码的具体问题是:
1) 如果QSlider::valueChanged() (signal) expects an integer as a parameter why do we only pass in QLCDNumber::display() (slot) 是void函数。因此,不会传入任何内容。
2) 在下面注释掉的代码中,我无法调用第二个插槽。 1 个信号可以调用的插槽数量是否有限制?如果有我如何去调用 PyQt5 中的多个插槽。
编辑:我相信是因为 printLabel() 不是定义的插槽,这就是我遇到问题的原因。我可以在 ::connect() 参数中包含任意数量的插槽吗?或者我是不是以一种 hacky 的方式来处理这个问题。
import sys
from PyQt5.QtCore import (Qt)
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def printLabel(self, str):
print(str)
def initUI(self):
lcd = QLCDNumber(self)
sld = QSlider(Qt.Horizontal, self)
vbox = QVBoxLayout()
vbox.addWidget(lcd)
vbox.addWidget(sld)
self.setLayout(vbox)
#This line works
sld.valueChanged.connect(lcd.display)
#This line does not work
#sld.valueChanged.connect(lcd.display, self.printLabel("hi"))
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
整理你的观点:
Qt5 文档包含至少 90% 的您需要了解的内容,因此在 PyQt5 文档中重复所有内容毫无意义,它主要集中在 PyQt 特有的功能上(例如,参见 Signals and Slots 文章)。 Qt5 是一个 C++ 库。您无需了解 C++ 即可使用 PyQt(或阅读 Qt 的优秀文档),但您很难期望完全避免使用它。
QSlider.valueChanged
信号 发送 一个 int 值到所有连接到它的插槽。QLCDNUmber.display
插槽 接收 字符串、整数或浮点对象(即它具有三个重载)。对于内置的 Qt 槽,必须有一个与信号发送相匹配的重载。但是PyQt中自定义槽可以是any python可调用对象,签名不匹配也没关系(任何多余的参数都会被丢弃) .话虽如此,可以通过使用pyqtSlot
装饰器为用户定义的插槽定义显式签名 (因此允许在 PyQt 中指定多个重载)。正如上面提到的PyQt文章第一节所解释的,信号和槽都可以有多个连接。文章还详细介绍了 PyQt 特定的 API(包括
pyqtSlot
),并给出了如何使用它们的示例。
以下是连接到多个插槽的示例:
class Example(QWidget):
...
def initUI(self):
...
#connect to a built-in slot
sld.valueChanged.connect(lcd.display)
#connect to a user-defined lot
sld.valueChanged.connect(self.printLabel)
#any python callable will do
sld.valueChanged.connect(lambda x: print('lambda:', x))
...
def printLabel(self, value):
print('printLabel:', value)