【问题标题】:function call through signal changes default keyed arguments to 'False'. Why?通过信号调用函数将默认键控参数更改为“False”。为什么?
【发布时间】:2019-10-18 16:57:42
【问题描述】:

当通过信号连接调用函数时

mybutton.clicked.connect(myfunction)

调用该函数时,其所有参数都设置为 False。即使已设置默认参数。这是预期的行为吗?

下面的代码显示了一个简单的示例。对于我的特殊情况,将所有参数设置为 False 并不是一个大问题,因为我可以简单地用 if 语句来捕捉它。但是,我认为了解为什么以这种方式实施它可能对进一步的项目有所帮助。

这个简单的程序显示了我所期望的行为。

def function(foo=None):
    print(foo)

function()

但是,在这个最小的 Qt 示例中,函数参数不再是“None”,而是“False”。

import sys
from PyQt5.QtWidgets import QMainWindow, QGridLayout, QWidget, QPushButton, QApplication

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        centralWidget = QWidget(self)
        self.setCentralWidget(centralWidget)
        gridLayout = QGridLayout(self)
        centralWidget.setLayout(gridLayout)
        btn = QPushButton("button",self)
        gridLayout.addWidget(btn)
        btn.clicked.connect(self.function)

    def function(self, foo=None):
        print(foo)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit( app.exec_() )

错误

我想,问题是:我是否必须忍受在我的函数中没有可用的默认值(即,一旦我注意到它们被设置为 False,我是否需要重置它们)或者有什么更聪明的方法吗?处理它?

【问题讨论】:

标签: python pyqt pyqt5 qpushbutton


【解决方案1】:

clicked是一个重载信号,即它们是2个同名信号不同签名。

clicked = QtCore.pyqtSignal([], [bool])
# clicked = QtCore.pyqtSignal()
# clicked = QtCore.pyqtSignal(bool)

更多详情请阅读this answer

建立连接时,PyQt 确定将使用哪个信号,在这种情况下,您的函数的参数类似于第二种形式,因此信号将发送布尔值 False,在您的情况下,它将替换默认值.

如果您不希望这种情况发生,那么您必须强制 PyQt 使用第一种形式,使用 @QtCore.pyqtSlot() 装饰器,这样它就不会向您发送任何参数,因此您的函数使用默认参数。

import sys
from PyQt5 import QtCore, QtWidgets


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        centralWidget = QtWidgets.QWidget()
        self.setCentralWidget(centralWidget)
        gridLayout = QtWidgets.QGridLayout(centralWidget)
        btn = QtWidgets.QPushButton("button")
        gridLayout.addWidget(btn)
        btn.clicked.connect(self.function)

    @QtCore.pyqtSlot()
    def function(self, foo=None):
        print(foo)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit(app.exec_())

输出:

None

【讨论】:

  • 很好的解释!这也令人惊讶地深入了解了 pyqtSlot 装饰器背后的工作原理。非常感谢:)
【解决方案2】:

另一种可能的解决方案是使用* 语法强制keyword-only parameters

class MainWindow(QtWidgets.QMainWindow):
    ...
    
    def function(self, *, foo=None):
        print(foo)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-26
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多