PyQt - 槽连接



管理信号-槽连接是 PyQt 的重要功能之一,它能够实现应用程序不同组件之间的通信。**connectSlotsByName()** 函数用于在 PyQt 中自动建立这些信号-槽连接,前提是代码是由 **pyuic5** 生成的。在信号重载的情况下,我们无法自动绑定信号-槽连接,因此需要手动干预。

使用 connectSlotsByName() 自动连接信号和槽

PyQt 中的 **connectSlotsByName()** 函数可以根据简单的命名约定自动建立信号到槽的连接。当 GUI 元素发出的信号与 Python 代码中的槽名称匹配时,PyQt 会自动建立连接。这种约定简化了事件处理,并减少了显式连接语句的需求。

自动信号槽连接的问题

对于具有相同信号名称但参数类型不同的重载信号,自动将槽连接到其中一个信号将变得困难。假设您有一个 **QSpinBox** 部件,它在值更改时发出两个信号:**valueChanged(int)** 和 **valueChanged(const QString &)**。如果实现了名为 on_spinbox_valueChanged 的槽,则默认情况下它将连接到信号的两个变体。因此,在每次值更改事件中,槽将被调用两次,一次带整数参数,一次带字符串参数。

使用 pyqtSlot() 处理重载信号

为了解决由重载信号引起的问题,可以使用 **pyqtSlot()** 装饰器来指定槽应该连接到的确切信号。通过使用 **pyqtSlot()** 装饰槽定义,开发人员可以确保精确的信号-槽映射,从而提高代码清晰度和功能性。

例如,要将槽专门连接到 **QSpinBox** 发出的 **valueChanged** 信号的整数变体,可以如下注释槽定义:

@pyqtSlot(int)
def on_spinbox_valueChanged(self, i):
   # Slot implementation for integer variant.
   pass

在这种情况下,槽只会响应带有整数参数的信号,忽略字符串变体。使用 **pyqtSlot()** 装饰器的这种过程使开发人员能够严格控制信号处理,使其符合应用程序的要求。

示例 1:处理整数变体信号

from PyQt5.QtWidgets import QApplication, QMainWindow, QSpinBox
from PyQt5.QtCore import pyqtSlot

class MainWindow(QMainWindow):
   def __init__(self):
      super().__init__()
      self.spinBox = QSpinBox(self)
      self.spinBox.valueChanged.connect(self.on_spinbox_valueChanged)

   @pyqtSlot(int)
   def on_spinbox_valueChanged(self, value):
      print("Integer value changed:", value)

if __name__ == "__main__":
   app = QApplication([])
   window = MainWindow()
   window.show()
   app.exec_()

输出

Handling Integer Variant Signal
Integer value changed: 5

示例 2:处理字符串变体信号

from PyQt5.QtWidgets import QApplication, QMainWindow, QSpinBox
from PyQt5.QtCore import pyqtSlot

class MainWindow(QMainWindow):
   def __init__(self):
      self.spinBox = QSpinBox(self)
      self.spinBox.valueChanged[str].connect(self.on_spinbox_valueChanged)

   @pyqtSlot(str)
   def on_spinbox_valueChanged(self, value):
      print("String value changed:", value)

if __name__ == "__main__":
   app = QApplication([])
   window = MainWindow()
   window.show()
   app.exec_()

输出

Handling Value Variant Signal
String value changed: 1
String value changed: 2
String value changed: 3
String value changed: 4
String value changed: 5

使用自定义槽名称区分信号变体

当需要处理重载信号的两个变体,但使用不同的槽实现时,可以使用 **pyqtSlot()** 装饰器的 **name** 参数分配自定义槽名称。这种方法允许将多个槽连接到同一个信号,其中每个槽可以处理特定信号变体。

示例

@pyqtSlot(int, name='on_spinbox_valueChanged')
def spinbox_int_value(self, i):
   # Slot implementation for integer variant.
   pass

@pyqtSlot(str, name='on_spinbox_valueChanged')
def spinbox_qstring_value(self, s):
   # Slot implementation for string variant.
   pass

在这里,定义了两个槽,每个槽都使用 **pyqtSlot()** 装饰器进行注释并分配了不同的名称。尽管共享相同的信号源,但这些槽将被单独连接,确保 **valueChanged** 信号的每个变体都被路由到相应的槽。

示例:使用自定义槽名称处理两个信号变体

from PyQt5.QtWidgets import QApplication, QMainWindow, QSpinBox
from PyQt5.QtCore import pyqtSlot

class MainWindow(QMainWindow):
   def __init__(self):
      super().__init__()
      self.spinBox = QSpinBox(self)
      self.spinBox.valueChanged[int].connect(self.spinbox_int_value)
      self.spinBox.valueChanged[str].connect(self.spinbox_qstring_value)

   @pyqtSlot(int, name='on_spinbox_valueChanged')
   def spinbox_int_value(self, value):
      print("Integer value changed:", value)

   @pyqtSlot(str, name='on_spinbox_valueChanged')
   def spinbox_qstring_value(self, value):
      print("String value changed:", value)

if __name__ == "__main__":
   app = QApplication([])
   window = MainWindow()
   window.show()
   app.exec_()

输出

Handling Both Int String Variant
String value changed: 1
Integer value changed: 1
String value changed: 2
Integer value changed: 2
String value changed: 3
Integer value changed: 3
String value changed: 4
Integer value changed: 4
String value changed: 5
Integer value changed: 5
广告