【发布时间】:2021-11-21 07:20:18
【问题描述】:
继之前的问题之后,我现在可以从字典创建 Pyqt QTreeWidget,编辑树并将其保存到并编辑字典。但是,当我谈到包含字典列表的字典值时,它会编译同一父级下的值(请参阅字典,其中“属性”键包含字典列表,并输出到下面的 QTreeWidget)
self.d = {'TestName': {'Ref': 'ABC/DEF', 'Property': [{'Number': '2', 'Zipcode': '0002234',
'KeyAvailable': 'Yes'}, {'Number': '3',
'Zipcode': '2342444'}]}}
为了简洁起见,为第二个列表项(字典)设置另一个“属性”父级可能会更好。我遇到的主要问题是转换回字典,因为此时最后一个条目会覆盖前一个条目,如果其中一个字典中有一个额外的键(在本例中为“KeyAvailable”),则会出现额外的问题。
这是转换回字典的输出:
{'TestName': {'Ref': 'ABC/DEF', 'Property': {'Number': '3', 'Zipcode': '2342444', 'KeyAvailable': 'Yes'}}}
在下面的“tree_from_dict”和“tree_2_dict”函数中是否有处理这些列表实例的简单解决方案?
import sys
from PyQt5.QtWidgets import QWidget, QApplication, QTreeWidget, QTreeWidgetItem, QPushButton, QMainWindow
from PyQt5.QtCore import *
class MyMainWindow(QMainWindow):
def __init__(self, dialog):
QMainWindow.__init__(self)
self.d = {'TestName': {'Ref': 'ABC/DEF', 'Property': [{'Number': '2', 'Zipcode': '0002234',
'KeyAvailable': 'Yes'}, {'Number': '3',
'Zipcode': '2342444'}]}}
self.setWindowTitle('Example')
self.setGeometry(20, 20, 400, 400)
central = QWidget(self)
self.setCentralWidget(central)
self.button = QPushButton('Save button', central)
self.button.move(100, 350)
self.tree = QTreeWidget(self.centralWidget())
self.tree.setGeometry(QRect(30, 30, 300, 300))
self.tree.setColumnCount(2)
self.tree.setHeaderLabels(["XML Property", "Value"])
self.tree.itemDoubleClicked.connect(self.editItem)
self.button.clicked.connect(self.save_changes)
self.tree_from_dict(data=self.d, parent=self.tree)
def editItem(self, item, column):
try:
if column == 1:
item.setFlags(item.flags() | Qt.ItemIsEditable)
else:
pass
except Exception as e:
print(e)
def tree_from_dict(self, data=None, parent=None):
for key, value in data.items():
item = QTreeWidgetItem(parent)
item.setText(0, key)
if isinstance(value, dict):
self.tree_from_dict(data=value, parent=item)
elif isinstance(value, list):
[self.tree_from_dict(i, parent=item) for idx, i in enumerate(value)]
else:
item.setText(1, value)
def save_changes(self):
d = self.tree_2_dict(self.tree.invisibleRootItem())
print(d)
def tree_2_dict(self, parent, d=None):
if d is None:
d = {}
for index in range(parent.childCount()):
child = parent.child(index)
if child.childCount():
self.tree_2_dict(child, d.setdefault(child.text(0), {}))
else:
d[child.text(0)] = child.text(1)
return d
if __name__ == '__main__':
app = QApplication(sys.argv)
dialog = QMainWindow()
foo = MyMainWindow(dialog)
foo.show()
sys.exit(app.exec_())
【问题讨论】:
-
您对结构有控制权,还是来自第三方?您是否需要在应用程序中保留该特定数据结构?您需要首先决定如何呈现信息,然后设计一个合适的数据结构来适应它。
-
嗨@ekhumoro,我正在使用xmltodict,但只是在我的XML 的“正文”部分。然后,我希望通过以 QTreeWidget 的形式呈现 dict 来向用户呈现主体标签和值,允许他们进行任何编辑。然后,我希望将这些编辑转换回字典,以便稍后在创建 XML 时使用。 XML 中的重复标记名称通过 xmltodict 转换为带有 dicts 列表的单个键,因此我希望使用该格式,以便更轻松地通过 xmltodict.unparse 函数创建 XML。
-
我应该添加,理想情况下,我想在 QTreeview 中为每个列表项(dict)显示重复的父级,但我更关心在将 Qtreewidget 转换回来时使用 xmltodict 格式到一个字典
-
您的解决方案是包含多个 Property 字段还是您更愿意只包含一个(如您的示例所示)?调用
tree_2_dict函数时是否要获取原始的XML结构? -
嗨@angelogro,理想情况下,我希望QTreeWidget中有多个“属性”字段,以提供更清晰的外观,或者是否有更清晰的方法将两个dict内容分开在同一个'财产的父母?但如果这很难做到,我主要关心的是在 QTreeWidget 中进行任何编辑后运行 tree_2_dict 函数时再次恢复原始字典结构,这最终将使我能够运行 xmltodict.unparse 来构建 XML又回来了。
标签: python dictionary pyqt pyqt5 qtreewidget