我在使用 Python 3、PyQt5 和 Qt5 的应用程序中遇到语法/理解问题。我不确定其中哪一个导致了问题。
我负责将在 Windows 下运行的 GUI 应用程序移植到 Linux 上,并使用更新版本的库。我无法访问在 Windows 下运行的原始版本。
在几个地方我看到:
menu = QMenu(self)
action = menu.addAction("Some string")
action.triggered[()].connect(self.handler)
我认为这曾经有效。我正在移植到 Python 3.5、PyQt 5.7 和 Qt 5.7。我有理由相信代码是为每个版本的早期版本编写的。
现在执行它会在
'there is no matching overloaded signal'
段上生成 action.triggered[()]
错误。
通过猜测并查看我在某处找到的几个示例,我将最后一行更改为:
action.triggered.connect(self.handler)
现在似乎可以工作了。
有人可以解释一下原始的
triggered[()]
语法的含义/作用是什么,以及明显的变化是在哪个“产品”中——如果能够阅读到它在哪里发生了变化,那就太好了?我的替换只是 triggered
正确/相同的行为吗?
相关更改发生在 PyQt-5.3 中。简单地删除旧语法不完全安全,因为这很容易在当前和未来的代码中产生微妙的错误。
问题在于某些信号(如
triggered
)将始终发送默认布尔值,除非您采取措施消除它。 Qt 像这样定义这些信号:
triggered(bool checked = false)
PyQt 之前将其实现为两个重载:
triggered(bool checked)
triggered()
如果您想明确选择后一个重载,则必须使用以下稍微尴尬的语法:
triggered[()].connect(slot)
但是现在这不再是一种选择,因为只实现了第一个重载。因此,为了获得完全相同相同的行为,有必要像这样包装处理程序:
triggered.connect(lambda checked: slot())
或者像这样装饰它:
@QtCore.pyqtSlot()
def handleTriggered(self):
pass
否则,很容易陷入一个小陷阱。想象一下你有一个这样定义的方法:
def frobnicate(self, foobar=True):
if foobar:
# do something nice
else:
# empty my home directory without prompting
后来,您决定将其连接到一个按钮,如下所示:
self.button.clicked.connect(self.frobnicate)
一切看起来都很好,直到您发现
clicked
信号的工作方式与 triggered
一样,并且默认情况下始终发送 False
...
当然,如果您绝对确定您将永远不会连接带有参数的插槽,例如
triggered
和clicked
,您可以按照上面所示的简单方式将它们全部连接起来。但是,实际上,这只是一场等待发生的事故......