How to implement itemChecked and itemUnchecked signals for QTreeWidget in PyQt4?

Where are the itemChecked and itemUnchecked signals on a QTreeWidget ?

Qt Signals: (quote from PyQt4 QTreeWidget documentation page) void currentItemChanged (QTreeWidgetItem *,QTreeWidgetItem *) void itemActivated (QTreeWidgetItem *,int) void itemChanged (QTreeWidgetItem *,int) void itemClicked (QTreeWidgetItem *,int) void itemCollapsed (QTreeWidgetItem *) void itemDoubleClicked (QTreeWidgetItem *,int) void itemEntered (QTreeWidgetItem *,int) void itemExpanded (QTreeWidgetItem *) void itemPressed (QTreeWidgetItem *,int) void itemSelectionChanged () 

At the moment, I solved it as follows:

 self.treeWidget.itemClicked.connect (self.handle) def handle (item, column): print 'emitted!', item.text(column) if item.checkState(column) == QtCore.Qt.Checked: # there are a lot of my functions inside which work with item data self.handleChecked(item, column) elif item.checkState(column) == QtCore.Qt.Unchecked: self.handleUnchecked(item, column) 

But this is a bad decision for me, because itemClicked publishes in so many cases. It is emitted when left / right clicks on the text of an element, which is absolutely unnecessary (I have heavy functions inside self.handleChecked and unnecessary calls from them when opening the context menu are pretty lousy).

Well, I also tried using itemChanged :

 self.treeWidget.itemChanged.connect (self.handle) 

but in this case the situation is even worse! The self.handle function calls itself recursively to infinity and beyond, because my functions inside self.handleChecked change the data of the element, and this signal emits again and again. In addition, I need a signal that is emitted only when the flag is switched.

Can someone tell me what I'm doing wrong?

+4
source share
1 answer

To avoid recursion issues when using the itemChanged signal, try temporarily blocking signals until the handler completes:

 def handle(self, item, column): self.treeWidget.blockSignals(True) if item.checkState(column) == QtCore.Qt.Checked: self.handleChecked(item, column) elif item.checkState(column) == QtCore.Qt.Unchecked: self.handleUnchecked(item, column) self.treeWidget.blockSignals(False) 

UPDATE

Another part of your question asked about the emission of a signal only when checking an element.

One way to do this is to subclass QTreeWidgetItem and override its setData :

 class TreeWidgetItem(QtGui.QTreeWidgetItem): def setData(self, column, role, value): state = self.checkState(column) QtGui.QTreeWidgetItem.setData(self, column, role, value) if (role == QtCore.Qt.CheckStateRole and state != self.checkState(column)): treewidget = self.treeWidget() if treewidget is not None: treewidget.itemChecked.emit(self, column) class Window(QtGui.QTreeWidget): itemChecked = QtCore.pyqtSignal(object, int) def __init__(self, rows, columns): QtGui.QTreeWidget.__init__(self) self.itemChecked.connect(self.handleItemChecked) def handleItemChecked(self, item, column): print 'ItemChecked', int(item.checkState(column)) 
+10
source

All Articles