mardi 3 mars 2015

PyQt QTreeWidget - odd delay when setting all checkboxes to unchecked

I am building an application with PyQt4 and Python3 that is using a QTreeWidget to give users a way to select what portions of their data that they want interact with after it has been loaded into the application.


The tree usually has 3 levels. I'll refer to them as Grandparent (folder), Parent (header), and child (sweep).


As part of this I have included a button to simply clear all the checkboxes (i.e. set them all to Unchecked). However, I'm getting some strange behavior when I do this. Explained:



  • If a Grandparent is fully checked (i.e. not partially checked), clearing works fine

  • If, however, just one child, for example, is checked (meaning the Parent and Grandparent are both partially checked), there is a delay to setting the Parent and Grandparent to unchecked (I see the delay by just watching when the checkbox goes from partially checked to unchecked). The child changes from checked to unchecked instantly, but there is a multi-second delay to the others changes.


This second observation there is not consistent in the way it occurs. Sometimes, for example, both the transition from partially checked to unchecked for the Parent and Grandparent hangs for both of them. Other times, the Grandparent will change instantly but the Parent will hang, changing a few seconds later.


Similar to above, if a one of the Parent items is checked (so, Grandparent partially checked, all children of Parent are fully checked), trying to clear all the check boxes results in all of the Parent and Child checkboxes to transition instantly, but the Grandparent checkbox hangs for a period of time before transitioning from partially checked to unchecked.


Simplified code that will produce the issue:



class MyTree(QtGui.QWidget):

def __init__(self):
super().__init__()

layout = QtGui.QVBoxLayout(self)

self.tree = QtGui.QTreeWidget()
clear_btn = QtGui.QPushButton("Clear Checkboxes")
clear_btn.clicked.connect(self.clear_checked)

self.update_tree()
layout.addWidget(self.tree)
layout.addWidget(clear_btn)

def update_tree(self):
folders = {'folder1': {'signal1': ['Sweep1', 'Sweep2'], 'signal2': ['Sweep1', 'Sweep2']},
'folder2': {'signal1': ['Sweep1', 'Sweep2'], 'signal2': ['Sweep1', 'Sweep2']}}

for folder, headers in sorted(folders.items()):
grandparent_item = QtGui.QTreeWidgetItem(self.tree)
grandparent_item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsTristate | QtCore.Qt.ItemIsUserCheckable)
grandparent_item.setText(0, folder)

for header, sweeps in sorted(headers.items()):
parent_item = QtGui.QTreeWidgetItem(grandparent_item)
parent_item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsTristate | QtCore.Qt.ItemIsUserCheckable)
parent_item.setCheckState(0, QtCore.Qt.Unchecked)
parent_item.setText(0, header)

for sweep in sweeps:
child_item = QtGui.QTreeWidgetItem(parent_item)
child_item.setCheckState(0, QtCore.Qt.Unchecked)
child_item.setText(0, sweep)

def clear_checked(self):
root = self.tree.invisibleRootItem()
folder_count = root.childCount()

for i in range(folder_count):
folder = root.child(i)

folder.setCheckState(0, QtCore.Qt.Unchecked)


So, tests would be:



  • Check "folder1" and try "Clear checkboxes" - This should work fine

  • Check "Sweep1" under "signal1" under "folder1" and try "Clear checkboxes" - this should produce the issue describe above

  • Check "signal1" under "folder1" and try "Clear checkboxes" - this should produce the issue described above


Not sure how to even approach this problem, so any suggestions would be appreciated.





Aucun commentaire:

Enregistrer un commentaire