从QTreeWidgetItem SubClass PyQt / PySide发出信号的替代方案

时间:2017-10-05 18:46:48

标签: python pyqt pyqt5 signals-slots qtreewidgetitem

我正在实现一个gui分析软件,该软件使用带有几个自定义TreeWidgetItem类的QTreeWidget。树中的每个项目或多或少地负责其自己的书籍,以跟踪附加到其上的数据集和对象。我希望能够从Custom QTreeWidgetItems的函数中发出信号,但是下面的代码会导致myTWItem无法转换为QObject的错误。有没有办法以这种方式从QTreeWidgetItem发出信号?

import sys
from PyQt5 import QtCore, QtWidgets, QtGui


class myTWItem(QtWidgets.QTreeWidgetItem):
    childAdded = QtCore.pyqtSignal(object)

    def addChild(self, child):
        super(myTWItem, self).addChild(child)
        self.childAdded.emit(child)

app = QtWidgets.QApplication(sys.argv)
tw = QtWidgets.QTreeWidget()

item = myTWItem()

tw.addTopLevelItem(item)
item.setText(0, "James")

child = QtWidgets.QTreeWidgetItem()
child.setText(0, "Braddock")
item.addChild(child)

tw.show()
sys.exit(app.exec_())

输出:

>>Traceback (most recent call last):
>>  File "C:/Coding/Python/dataquick/sandbox/treewidgettest.py", line 22, in <module>
>>    item.addChild(child)
>>  File "C:/Coding/Python/dataquick/sandbox/treewidgettest.py", line 10, in addChild
>>    self.childAdded.emit(child)
>>TypeError: myTWItem cannot be converted to PyQt5.QtCore.QObject in this context
>>
>>Process finished with exit code 1

1 个答案:

答案 0 :(得分:1)

执行此操作的一种方法是在父树窗口小部件上定义自定义信号。然后,从项目中,您将能够:

tree = self.treeWidget()
if tree is not None:
    tree.childAdded.emit(child)

当然,这里明显的缺点是,这对于尚未添加到树中的项目不起作用(尽管在某些情况下,这可能是一个优势)。

另一种方法是创建一个继承QObject的单独信号类。为了保持轻量级,最好使用它的共享实例,而不是为每个项创建一个。这也可以避免必须为树中的每个项目建立连接:

import sys
from PyQt5 import QtCore, QtWidgets, QtGui

class TWSignals(QtCore.QObject):
    childAdded = QtCore.pyqtSignal(object)

class myTWItem(QtWidgets.QTreeWidgetItem):
    signals = TWSignals()

    def addChild(self, child):
        super(myTWItem, self).addChild(child)
        self.signals.childAdded.emit(child)

app = QtWidgets.QApplication(sys.argv)
tw = QtWidgets.QTreeWidget()

# connect using the class attribute
myTWItem.signals.childAdded.connect(
    lambda item: print('child added:', item.text(0)))

item = myTWItem()

tw.addTopLevelItem(item)
item.setText(0, "James")

child = QtWidgets.QTreeWidgetItem()
child.setText(0, "Braddock")
item.addChild(child)

tw.show()
sys.exit(app.exec_())

(注意:当然,以这两种方式中的任何一种方式处理都意味着sender()不会返回您通常期望的内容。