Как добавить несколько комбинированных списков как дочерний элемент в QTreeWidgetItem - PullRequest
1 голос
/ 19 марта 2020

Я нахожусь в ситуации, когда мне нужно динамически генерировать пользовательский интерфейс на основе случайно различающегося количества родителей со случайным количеством вложенных детей.

Когда дочерний элемент QTreeWidgetItem раскрыт, его дочерний элемент должен выглядит так:

-Parent
    -Child
        -ComboBox | ComboBox | ComboBox | ComboBox

Я пытался setItemWidget безуспешно и только вылетает. Ниже приведен простой пример того, что я пытаюсь сделать.

#! /usr/bin/env python

from PySide2 import QtWidgets, QtCore


class TestUI(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(TestUI, self).__init__(parent)

    def setup_UI(self):
        # Setup the main window
        self.MainWindow = QtWidgets.QMainWindow(self.parent)
        self.MainWindow.resize(900, 400)
        self.MainWindow.setMinimumSize(QtCore.QSize(900, 600))
        self.MainWindow.setObjectName("TestUI")

        # Create the main tree
        self.tree_widget = QtWidgets.QTreeWidget(self.MainWindow)
        self.gridLayout = QtWidgets.QGridLayout(self.tree_widget)
        self.MainWindow.setCentralWidget(self.tree_widget)

        # Create a root parent item, repeat this for as many parents as needed
        top_item = QtWidgets.QTreeWidgetItem(self.tree_widget)
        top_item.setText(0, "Top_Parent_Item")
        self.tree_widget.addTopLevelItem(top_item)

        # Create child item
        child_item = QtWidgets.QTreeWidgetItem(top_item)
        child_item.setText(0, "Child_Item")
        top_item.addChild(child_item)

        # Create the child to the child that we use to replace the item with the combobox widget
        nested_child_item = QtWidgets.QTreeWidgetItem(child_item)
        nested_child_item.setText(0, "Nested_Child_Item")
        child_item.addChild(nested_child_item)

        # Create the combobox widget for all comboxes
        widget = QtWidgets.QWidget()
        layout = QtWidgets.QVBoxLayout(widget)

        # Repeat this 4 times for 4 comboboxes
        combo_box_1 = QtWidgets.QComboBox()
        values = ["1", "2", "3", "4", "5"]
        combo_box_1.addItems(values)
        layout.addWidget(combo_box_1)

        # Apply layout with everything in it
        widget.setLayout(layout)

        # This line hard crashes my code but no idea how else to go about adding a widget to an item.
        self.tree_widget.setItemWidget(nested_child_item, 1, combo_box_1)

        #Show the UI
        self.MainWindow.show()

# Launch UI
test = TestUI()
test.setup_UI()

1 Ответ

1 голос
/ 19 марта 2020

Прежде чем ответить на ваш вопрос, следует отметить, что в вашем коде много несоответствий: у вас есть QMainWindow, являющееся дочерним по отношению к другому QMainWindow, есть виджеты, которые бесполезны и т. Д. c. Я рекомендую вам хорошо проанализировать ваш код, если он имеет смысл или нет.

С другой стороны, QTreeWidget по умолчанию имеет столбец, поэтому вы можете установить только QComboBox, а индексы столбцов начинаются с 0. Если вы чтобы появилось больше столбцов, вы должны установить их явно.

#! /usr/bin/env python

from PySide2 import QtWidgets, QtCore


class TestUI(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(TestUI, self).__init__(parent)

    def setup_UI(self):
        # Create the main tree
        self.tree_widget = QtWidgets.QTreeWidget()
        self.setCentralWidget(self.tree_widget)

        self.tree_widget.setColumnCount(4)

        top_item = QtWidgets.QTreeWidgetItem(self.tree_widget)
        top_item.setText(0, "Top_Parent_Item")
        self.tree_widget.addTopLevelItem(top_item)

        child_item = QtWidgets.QTreeWidgetItem(top_item)
        child_item.setText(0, "Child_Item")
        top_item.addChild(child_item)

        nested_child_item = QtWidgets.QTreeWidgetItem(child_item)
        nested_child_item.setText(0, "Nested_Child_Item")
        child_item.addChild(nested_child_item)

        for i in range(self.tree_widget.columnCount()):
            combo_box = QtWidgets.QComboBox(self.tree_widget)
            values = ["1", "2", "3", "4", "5"]
            combo_box.addItems(values)

            self.tree_widget.setItemWidget(nested_child_item, i, combo_box)

        self.tree_widget.expandAll()
        self.resize(640, 480)

        self.show()


if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    test = TestUI()
    test.setup_UI()
    app.exec_()

enter image description here

Обновление:

Другой Возможное решение - использовать делегата для автоматического предоставления QComboBox:

#! /usr/bin/env python

from PySide2 import QtWidgets, QtCore


class StyledItemDelegate(QtWidgets.QStyledItemDelegate):
    def paint(self, painter, option, index):
        if index.parent().parent().isValid():
            if isinstance(option.widget, QtWidgets.QAbstractItemView):
                option.widget.openPersistentEditor(index)
        else:
            super(StyledItemDelegate, self).paint(painter, option, index)

    def createEditor(self, parent, option, index):
        if index.parent().parent().isValid():
            editor = QtWidgets.QComboBox(parent)
            values = ["1", "2", "3", "4", "5"]
            editor.addItems(values)
            return editor
        return super(StyledItemDelegate, self).createEditor(parent, option, index)

    def updateEditorGeometry(self, editor, option, index):
        editor.setContentsMargins(0, 0, 0, 0)
        editor.setGeometry(option.rect)

    def sizeHint(self, option, index):
        s = super(StyledItemDelegate, self).sizeHint(option, index)
        s.setHeight(s.height() * 1.5)
        return s


class TestUI(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(TestUI, self).__init__(parent)

    def setup_UI(self):
        # Create the main tree
        self.tree_widget = QtWidgets.QTreeWidget()
        self.setCentralWidget(self.tree_widget)

        delegate = StyledItemDelegate(self)
        self.tree_widget.setItemDelegate(delegate)
        self.tree_widget.setColumnCount(4)

        top_item = QtWidgets.QTreeWidgetItem(self.tree_widget)
        top_item.setText(0, "Top_Parent_Item")
        self.tree_widget.addTopLevelItem(top_item)

        child_item = QtWidgets.QTreeWidgetItem(top_item)
        child_item.setText(0, "Child_Item")
        top_item.addChild(child_item)

        nested_child_item = QtWidgets.QTreeWidgetItem(child_item)
        child_item.addChild(nested_child_item)

        self.tree_widget.expandAll()
        self.resize(640, 480)

        self.show()


if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    test = TestUI()
    test.setup_UI()
    app.exec_()
...