我处于一种情况,我需要根据随机不同数量的父母和随机数量的嵌套孩子来动态生成UI。
当子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()
在回答您的问题之前,应注意代码中存在许多不一致之处:您有一个QMainWindow是另一个QMainWindow的子级,有一些无用的小部件,等等。我建议您对代码进行仔细分析是否有意义。
另一方面,默认的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_()
更新:
另一个可能的解决方案是使用委托来自动提供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_()