信号和缺少位置参数

时间:2016-07-15 15:36:40

标签: python pyqt

我在QtDesigner(SourceForm,DestinationForm)中开发了两个窗口,并使用pyuic5转换它们的.ui页面。我使用第三类WController作为使用堆叠小部件在两个窗口之间导航的方法。我在SourceForm中有一个按钮,用treeWidget填充一些数据,方法handle_treewidget_itemchange指示当treeWidget中的特定项目使用{{1}进行检查或取消选中时会发生什么}}。据我所知,self.treeWidget.itemChanged.connect(self.handle_treewidget_itemchange)会自动将更改内容的行和列发送到插槽,但是当第一次调用itemChanged.connect时,我的脚本会因TypeError崩溃:

handle_treewidget_itemchange(self,row,col)

如果我取出TypeError: handle_treewidget_itemchange() missing 2 required positional arguments: 'row' and 'col'row args,脚本运行正常。当我最初在col .py文件中同时拥有方法和调用时,我的代码按预期工作...也许这只是一个范围问题?我开始认为尝试使用PyQt虽然仍然没有经验的Python一个坏主意:(

我试图将代码删除到基本要素:

SourceForm

2 个答案:

答案 0 :(得分:0)

使用pyqtSlot时需要小心,因为它很容易破坏正在装饰的插槽的签名。在您的情况下,它已将插槽重新定义为没有参数,这解释了为什么您收到该错误消息。简单的解决方法是简单地删除它,因为没有它你的例子将完美地工作。

pyqtSlot的主要目的是允许定义槽的几个不同重载,每个重载具有不同的签名。在进行跨线程连接时,有时也可能需要它。但是,这些用例相对较少,在大多数PyQt / PySide应用程序中,根本不需要使用pyqtSlot。信号可以连接到任何 python可调用对象,无论它是否被装饰为插槽。

答案 1 :(得分:0)

这个问题已经有了一个公认的答案,但无论如何我都会给我。

有问题的广告位已连接到itemChanged(QTreeWidgetItem *item, int column)信号,因此pyqtSlot应该看起来像@pyqtSlot(QTreeWidgetItem, int)

现在,正如ekhumoro指出的那样,PyQt接受将信号连接到任何Python可调用对象,无论是方法,lambda还是具有__call__方法的仿函数。但这样做安全性较低,而不是使用@pyqtSlot

例如,当源QObject(发出信号的人)被破坏,或者目标QObject(拥有Qt插槽)被破坏时,Qt会自动断开连接。例如,如果删除窗口小部件,则无需向其发出其他地方发生的事件的信号。如果使用@pyqtSlot,则会在您的类中创建一个真正的Qt插槽,因此可以应用此断开连接机制。此外,Qt没有对目标QObject的强引用,因此可以将其删除。

如果使用任何可调用的方法,例如非装饰的绑定方法,Qt将无法识别连接的目标QObject。更糟糕的是,由于你传递了一个Python可调用的,它将保存一个强引用,并且可调用(绑定方法)将依次保存对最终QObject的引用,因此你的目标QObject将不会被垃圾收集,直到你手动断开它,或删除源QObject。

请参阅此代码,您可以启用一个连接或另一个连接,并观察行为的差异,这表明窗口是否可以被垃圾收集:

from PyQt5.QtWidgets import QApplication, QMainWindow

app = QApplication([])

def create_win():
    win = QMainWindow()
    win.show()

    # case 1
    # app.aboutToQuit.connect(win.repaint)  # this is a qt slot, so win can be deleted

    # case 2
    # app.aboutToQuit.connect(win.size)  # this is not a qt slot, so win can't be deleted

    # win should get garbage-collected here

create_win()

app.exec_()