如何将带有可变参数的多个 PyQt 信号连接到单个 slot/signal 转发器

How to connect multiple PyQt Signals w/ variable arguments to single slot/signal repeater

示例:

class MyClass(QObject):
    signal_1 = pyqtSignal(str, int)
    signal_2 = pyqtSignal(int, int)
    signal_3 = pyqtSignal(str, int, int)

假设这些信号中的每一个都连接到别处以执行各种功能,但是,当发出 any 信号时,我还想执行一个特定的功能。这个不分青红皂白的函数只关心,比方说,信号发出的最后一个 int 参数。该插槽表面上看起来像:

class OtherClass(QObject):

    ...

    @pyqtSlot(int)
    def unifiedResponse(self, index):
        # Here I would do something with that index

有没有办法将任意数量的带有任意参数的信号直接连接到插槽或中继器信号?

如果有像这样定义插槽的方法:

@pyqtSlot(???)
def unifiedResponse(self, *args):
    important_var = args[-1]

然后我可以简单地捕获最后一个参数。但是,我一直没有确定如何形成插槽签名。

更新:

我可能已经回答了我自己的问题,使用 lambdas:

signal_1.connect(lambda _, source: OtherClass.unifiedResponse(source))
signal_2.connect(lambda _, source: OtherClass.unifiedResponse(source))
signal_3.connect(lambda _, _, source: OtherClass.unifiedResponse(source))

然而,下面@eyllanesc 的解决方案是首选,因为它允许更大的灵活性,信号数越大。

你必须通过几个pyqtSlot来设置信号的所有签名:

from PyQt5.QtCore import pyqtSignal, pyqtSlot, QCoreApplication, QObject, QTimer


class MyClass(QObject):
    signal_1 = pyqtSignal(str, int)
    signal_2 = pyqtSignal(int, int)
    signal_3 = pyqtSignal(str, int, int)


class OtherClass(QObject):
    @pyqtSlot(str, int)
    @pyqtSlot(int, int)
    @pyqtSlot(str, int, int)
    def unifiedResponse(self, *args):
        print(args)


def main():
    import sys

    app = QCoreApplication(sys.argv)

    sender = MyClass()
    receiver = OtherClass()

    sender.signal_1.connect(receiver.unifiedResponse)
    sender.signal_2.connect(receiver.unifiedResponse)
    sender.signal_3.connect(receiver.unifiedResponse)

    def on_timeout():
        sender.signal_1.emit("Whosebug", 1)
        sender.signal_2.emit(1, 2)
        sender.signal_3.emit("Whosebug", 1, 2)

        QTimer.singleShot(1000, QCoreApplication.quit)

    QTimer.singleShot(1000, on_timeout)

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

如果通常要发送多种类型的数据,那么最好使用更通用的数据类型,例如列表(或对象):

class MyClass(QObject):
    signal_1 = pyqtSignal(list)
    signal_2 = pyqtSignal(list)
    signal_3 = pyqtSignal(list)


class OtherClass(QObject):
    @pyqtSlot(list)
    def unifiedResponse(self, args):
        print(args)


def main():
    import sys

    app = QCoreApplication(sys.argv)

    sender = MyClass()
    receiver = OtherClass()

    sender.signal_1.connect(receiver.unifiedResponse)
    sender.signal_2.connect(receiver.unifiedResponse)
    sender.signal_3.connect(receiver.unifiedResponse)

    def on_timeout():
        sender.signal_1.emit(["Whosebug", 1])
        sender.signal_2.emit([1, 2])
        sender.signal_3.emit(["Whosebug", 1, 2])

        QTimer.singleShot(1000, QCoreApplication.quit)

    QTimer.singleShot(1000, on_timeout)

    sys.exit(app.exec_())

更新:

没有优雅的方法来访问最后一个元素,但是第一个元素,因为槽签名必须是信号签名的子集,例如带有签名 "int" 的槽可以接受带有签名的信号第一个类型为 "int",其他参数被丢弃:

from PyQt5.QtCore import pyqtSignal, pyqtSlot, QCoreApplication, QObject, QTimer


class MyClass(QObject):
    signal_1 = pyqtSignal(int, str)
    signal_2 = pyqtSignal(int, int)
    signal_3 = pyqtSignal(int, str, int)


class OtherClass(QObject):
    @pyqtSlot(int)
    def unifiedResponse(self, index):
        print(index)


def main():
    import sys

    app = QCoreApplication(sys.argv)

    sender = MyClass()
    receiver = OtherClass()

    sender.signal_1.connect(receiver.unifiedResponse)
    sender.signal_2.connect(receiver.unifiedResponse)
    sender.signal_3.connect(receiver.unifiedResponse)

    def on_timeout():
        sender.signal_1.emit(1, "Whosebug")
        sender.signal_2.emit(2, 2)
        sender.signal_3.emit(3, "Whosebug", 1)

        QTimer.singleShot(1000, QCoreApplication.quit)

    QTimer.singleShot(1000, on_timeout)

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

我在将多个带有可变参数的 PyQt 信号连接到单个插槽时遇到了问题。

这是我找到的用于连接从 input_lineEdit_widgetsvalidate_values[= 的所有小部件的解决方案12=]

class View_Controller():

    def connect_signals(self,ui):

        #This is a list of lineEdit widgets from a QtWidgets.QMainWindow (ui)
        input_lineEdit_widgets = [ui.prim_press_lineEdit, ui.gas_vol_lineEdit, ui.melt_1_temp_lineEdit,
                                 ui.melt_1_time_lineEdit, ui.melt_1_flow_lineEdit, ui.melt_2_temp_lineEdit,
                                 ui.melt_2_time_lineEdit, ui.melt_2_flow_lineEdit]

        for widgets in input_lineEdit_widgets:
            widgets.textChanged.connect(lambda *args, widgets = widgets: self.validate_values(widgets))


    def validate_values(self, widget):
        print(widget.objectName())

更多详情here