Pyqt将插槽连接到具有默认参数的函数而没有lambda [重复]

Posted

技术标签:

【中文标题】Pyqt将插槽连接到具有默认参数的函数而没有lambda [重复]【英文标题】:Pyqt connecting a slot to a function with default parameters without lambda [duplicate] 【发布时间】:2020-04-27 02:41:10 【问题描述】:

我在 Pyqt 中遇到了一个与解决 here 和 here 非常相似的问题,其中一个函数通过 lambda 使用不同的参数调用。

from PyQt4.QtCore import *
from PyQt4.QtGui import *

class MyForm(QMainWindow):
    def __init__(self, parent=None):
        super(MyForm, self).__init__(parent)
        button1 = QPushButton('Button 1')
        button2 = QPushButton('Button 2')
        button1.clicked.connect(lambda: self.on_button(1))
        button2.clicked.connect(lambda: self.on_button(2))

        layout = QHBoxLayout()
        layout.addWidget(button1)
        layout.addWidget(button2)

        main_frame = QWidget()
        main_frame.setLayout(layout)

        self.setCentralWidget(main_frame)

    def on_button(self, n):
        print('Button 0 clicked'.format(n))

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    form = MyForm()
    form.show()
    app.exec_()

我的两个问题是:

如何使用默认参数进行这项工作? 有没有不使用 lambda 函数的解决方案? (我想要这个的唯一原因是因为使用 lambda 函数感觉错误且过于复杂,我觉得可能有更简单的解决方案。)

我的(非工作)想法看起来像:

from PyQt4.QtCore import *
from PyQt4.QtGui import *

class MyForm(QMainWindow):
    def __init__(self, parent=None):
        super(MyForm, self).__init__(parent)
        button1 = QPushButton('Button 1')
        button2 = QPushButton('Button 2')
        button1.clicked.connect(self.on_button()) # this should call on_button with n set to default
        #button1.clicked.connect(lambda: self.on_button()) #this works, but uses a lambda
        button2.clicked.connect(lambda: self.on_button(2))

        layout = QHBoxLayout()
        layout.addWidget(button1)
        layout.addWidget(button2)

        main_frame = QWidget()
        main_frame.setLayout(layout)

        self.setCentralWidget(main_frame)

    def on_button(self, n=1): #using default argument
        print('Button 0 clicked'.format(n))

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    form = MyForm()
    form.show()
    app.exec_()

【问题讨论】:

【参考方案1】:

如果您不想使用 lambda,则语法应为 button1.clicked.connect(self.on_button)

但是QPushButton::clicked 有一个布尔值checked 参数(see the doc)。所以,n 参数永远不会采用默认值。

【讨论】:

【参考方案2】:

我通常使用functools.partials 来处理单个插槽处理来自不同来源的多个等效信号的情况:

from functools import partial

# in __init__
button1.clicked.connect(self.on_button)
button1.clicked.connect(partial(self.on_button, n=2))

# and using a slot with kwarg n=1 as in your code

在底层,这只是创建了一个中间包装函数,它添加了 kwarg,所以这与 lambda 非常相似,而且更多的是品味问题而不是真正的优势。

【讨论】:

以上是关于Pyqt将插槽连接到具有默认参数的函数而没有lambda [重复]的主要内容,如果未能解决你的问题,请参考以下文章

在不丢失默认信号参数的情况下将额外参数传递给 PyQt 插槽

pyQt5从dict创建按钮连接到具有附加值的函数

PYQT5 - 插槽函数不采用默认参数 [重复]

如何将 PyQt 插槽从后台线程连接到 gui 线程

PyQt 和 QML:如何在一个插槽或函数中处理多个信号

如何将信号连接到不同线程中的插槽