Search code examples
pythonpyqtpyqt4qtreewidget

Qt treewidget python; iterate columns


Given a tree widget in PyQt4 with some rows and columns:

1) Is there a way to easily iterate over all cells?

2) How can one check if a checkbox is checked apart from the first column?

So far I only managed to get the results of the checkboxes in the first column, see here.

For clarification here is the widget how I imagine it to look like: (the fourth column should be editable)

widget structure

from PyQt4.QtCore import * 
from PyQt4.QtGui import * 
import sys


def main(): 
    app     = QApplication (sys.argv)
    tree    = QTreeWidget ()
    item    = QTreeWidgetItem()

    tree.headerItem().setText(0, "col1")
    tree.headerItem().setText(1, "col2")
    tree.headerItem().setText(2, "col3")
    tree.headerItem().setText(3, "Notes")

    for ii in xrange(3):
        parent = QTreeWidgetItem(tree)
        parent.setText(0, "Parent {}".format(ii))
        parent.setFlags(parent.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
        for x in xrange(4):
            child = QTreeWidgetItem(parent)
            child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
            child.setText(0, "Child {}".format(x))
            child.setCheckState(0, Qt.Unchecked)

            #create the checkbox
            for i in xrange(1, 5):
                if i < 3:
                    child.setText(i, "")
                    child.setCheckState(i, Qt.Unchecked)
                if i == 3:
                    child.setText(i, "Any Notes?")
                    child.setFlags(child.flags() | Qt.ItemIsEditable)

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

if __name__ == '__main__':
    main()

Solution

  • One way to iterate over a tree-widget is to use QTreeWidgetItemIterator:

    def iter_tree_widget(root):
        iterator = QtGui.QTreeWidgetItemIterator(root)
        while True:
            item = iterator.value()
            if item is not None:
                yield item
                iterator += 1
            else:
                break
    

    The root argument can be either a tree-widget (to iterate over the whole tree), or a tree-widget-item (to iterate over a single branch).

    The iterator produces one item per row, and the columns of this item are accessed by simply specifying the column index:

    column = 0
    for item in iter_tree_widget(tree):
        print('State: %s, Text: "%s"' % (
              item.checkState(column), item.text(column)))