Problem with QTreeWidget.setHeaderItem

Hi, Matthias!

I'm not sure if this is problem with KLayout Qt bindings or with Qt itself.

When I use setHeaderItem KLayout duplicates item in header and general items area and crashes at exit ("double free or corruption"). I thought that widget argument is reason but with pya.QTreeWidgetItem() KLayout doesn't display header at all and crashes too.

As workaround I use setHeaderLabels.

I use KLayout 0.26.4 built with Qt 5.14.2.

Test code:

class Tree_Widget_Dialog(pya.QDialog):

    def __init__(self, parent, use_header_item):
        super(Tree_Widget_Dialog, self).__init__(parent)

        self.setWindowTitle('Test')
        self.resize(500, 500)

        vertical_layout = pya.QVBoxLayout(self)
        self.setLayout(vertical_layout)

        column_names = ['Column 1', 'Column 2', 'Column 3']

        tree_widget = pya.QTreeWidget(self)
        if use_header_item:
            header_item = pya.QTreeWidgetItem(tree_widget)
            header_item.setText(0, 'Tree')
            for index, column_name in enumerate(sorted(column_names), 1):
                header_item.setText(index, column_name)
            tree_widget.setHeaderItem(header_item)
        else:
            header_labels = ['Group']
            for column_name in column_names:
                header_labels.append(column_name)
            tree_widget.setHeaderLabels(header_labels)
        tree_widget.expandAll()
        vertical_layout.addWidget(tree_widget)

def test_qtreewidget():
    main_window = pya.Application.instance().main_window()
    Tree_Widget_Dialog(main_window, False).exec_()

Eugene.

Comments

  • Hi Eugene,

    Thanks for you perfect test cases. It's very helpful for me to understand your problem.

    Usually you don't need to use setHeaderItem. Your second approach is perfectly valid.

    The first approach does not work for two reasons - one due to Qt, one due to KLayout's Qt binding.

    First, if you create a QTreeWidgetItem with a QTreeWidget as a parent, the item is automatically added to the tree. But if you add it as header item additionally, it gets duplicated. Because there is a twofold ownership, the application crashes when the dialog is destroyed. You can solve this problem by creating the QTreeWidgetItem with no parent.

    Second, if you do so, KLayout will not notice that Qt takes over the ownership of the header item when you pass it to setHeaderItem. If you want that's a bug. So when Python exits the init function, it will delete the header item object which also makes the application crash. The workaround is to explicitly release the header item object from Python's ownership by using "_unmanage".

    The working code is here:

    class Tree_Widget_Dialog(pya.QDialog):
    
        def __init__(self, parent, use_header_item):
            super(Tree_Widget_Dialog, self).__init__(parent)
    
            self.setWindowTitle('Test')
            self.resize(500, 500)
    
            vertical_layout = pya.QVBoxLayout(self)
            self.setLayout(vertical_layout)
    
            column_names = ['Column 1', 'Column 2', 'Column 3']
    
            tree_widget = pya.QTreeWidget(self)
            if use_header_item:
                header_item = pya.QTreeWidgetItem()
                header_item.setText(0, 'Tree')
                for index, column_name in enumerate(sorted(column_names), 1):
                    header_item.setText(index, column_name)
                tree_widget.setHeaderItem(header_item)
                header_item._unmanage()
            else:
                header_labels = ['Group']
                for column_name in column_names:
                    header_labels.append(column_name)
                tree_widget.setHeaderLabels(header_labels)
            tree_widget.expandAll()
            vertical_layout.addWidget(tree_widget)
    
    def test_qtreewidget():
        main_window = pya.Application.instance().main_window()
        Tree_Widget_Dialog(main_window, True).exec_()
    
    test_qtreewidget()
    

    Best regards,

    Matthias

  • Hi, Matthias!

    Thank you for explanations! I'll try to use second approach if it'll allow to set check state for columns.

    Eugene.

Sign In or Register to comment.