从具有值列表的字典创建 Pyqt QtableWidget,然后返回到字典
Creating a Pyqt QtableWidget from a dictionary with list of values, and back to a dictionary
根据之前的问题,我现在可以从字典创建 Pyqt QTreeWidget,编辑树并将其保存到编辑字典。但是,当我涉及到包含字典列表的字典值时,它会编译同一父项下的值(请参阅字典,其中 'Property' 键包含字典列表,并输出到下面的 QTreeWidget)
self.d = {'TestName': {'Ref': 'ABC/DEF', 'Property': [{'Number': '2', 'Zipcode': '0002234',
'KeyAvailable': 'Yes'}, {'Number': '3',
'Zipcode': '2342444'}]}}
为了整洁起见,为第二个列表项(字典)设置 'Property' 的另一个父项可能会更好。我遇到的主要问题是转换回字典,因为在最后一个条目覆盖前一个条目的那一刻,如果其中一个字典中有一个额外的键(在本例中为 '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_())
我很确定这不是最优雅的解决方案。该函数现在检查 list
是否作为数据传递并添加 属性 与该列表中的元素一样多。
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):
for idx, i in enumerate(value):
if idx!=0:
item = QTreeWidgetItem(parent)
item.setText(0, key)
self.tree_from_dict(i, parent=item)
else:
item.setText(1, value)
另一个函数现在额外检查 属性 是否已经是 dict
的键。如果是这样,它将相应的值转换为 list
并附加新值。
def tree_2_dict(self, item, dic):
# Variable for saving all occuring property names in that scope
childrenNames=[]
for index in range(item.childCount()):
child = item.child(index)
if child.text(0) not in childrenNames:
childrenNames.append(child.text(0))
if child.childCount():
dic[child.text(0)]=self.tree_2_dict(child, {})
else:
dic[child.text(0)] = child.text(1)
else:
ele = dic[child.text(0)]
if child.childCount():
child_dic =self.tree_2_dict(child, {})
if isinstance(ele,list):
ele.append(child_dic)
else:
ele=[ele,child_dic]
else:
if isinstance(ele,list):
ele.append(child.text(1))
else:
ele=[ele,child.text(1)]
dic[child.text(0)] = ele
return dic
根据之前的问题,我现在可以从字典创建 Pyqt QTreeWidget,编辑树并将其保存到编辑字典。但是,当我涉及到包含字典列表的字典值时,它会编译同一父项下的值(请参阅字典,其中 'Property' 键包含字典列表,并输出到下面的 QTreeWidget)
self.d = {'TestName': {'Ref': 'ABC/DEF', 'Property': [{'Number': '2', 'Zipcode': '0002234',
'KeyAvailable': 'Yes'}, {'Number': '3',
'Zipcode': '2342444'}]}}
为了整洁起见,为第二个列表项(字典)设置 'Property' 的另一个父项可能会更好。我遇到的主要问题是转换回字典,因为在最后一个条目覆盖前一个条目的那一刻,如果其中一个字典中有一个额外的键(在本例中为 '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_())
我很确定这不是最优雅的解决方案。该函数现在检查 list
是否作为数据传递并添加 属性 与该列表中的元素一样多。
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):
for idx, i in enumerate(value):
if idx!=0:
item = QTreeWidgetItem(parent)
item.setText(0, key)
self.tree_from_dict(i, parent=item)
else:
item.setText(1, value)
另一个函数现在额外检查 属性 是否已经是 dict
的键。如果是这样,它将相应的值转换为 list
并附加新值。
def tree_2_dict(self, item, dic):
# Variable for saving all occuring property names in that scope
childrenNames=[]
for index in range(item.childCount()):
child = item.child(index)
if child.text(0) not in childrenNames:
childrenNames.append(child.text(0))
if child.childCount():
dic[child.text(0)]=self.tree_2_dict(child, {})
else:
dic[child.text(0)] = child.text(1)
else:
ele = dic[child.text(0)]
if child.childCount():
child_dic =self.tree_2_dict(child, {})
if isinstance(ele,list):
ele.append(child_dic)
else:
ele=[ele,child_dic]
else:
if isinstance(ele,list):
ele.append(child.text(1))
else:
ele=[ele,child.text(1)]
dic[child.text(0)] = ele
return dic