PyQt GUI:如何存储数据(类对象)?

时间:2018-09-26 09:39:39

标签: python pyqt pyqt4 qtreewidget

我最近开始编程python,并使用PyQt对我的第一个GUI进行了NMR数据的后处理和评估。该应用程序的当前版本如下所示: screenshot of the pyqt app

典型的工作流程是:

  1. 读取各种实验(通常是3D或4D(2D / 3D +时间/频率)图像堆栈的数据)
  2. 进行一些后期处理,例如定义感兴趣区域(ROI),拟合时间/频率分辨光谱,计算对比度等等
  3. 在GUI中可视化结果
  4. 以图像/图形/表格的形式导出结果,并带有合适的结果(xml)
  5. 保存工作区以便能够重新加载

4d图像堆栈与实验设置,图像重构设置,拟合结果等一起存储为我自己的MriData类的类对象:

class MriData:
   def __init__(self, path='', exp_num=0, exp_name=''):
       self.path = path
       self.exp_num = exp_num
       self.exp_name = exp_name    
       self.img_stack = np.array([])
       self.ROIs = []  # list of ROIs  
       self.settings= {}
       self.lmfit = {}
       ...

目前,我的MainWindow具有类型为list的属性“ mri_data”,其中存储了所有数据/类对象。如果我在左侧的QTreeWidget中选择(多个)实验和/或ROI,则始终检查该项目是否为顶级项目,并获得实验的索引(如果是ROI,则获取ROI的索引)然后访问“ mri_data”列表中的相应列表条目:

list_items: = self.QTreeWidget.selectedItems()
list_idx = self.QTreeWidget.selectedIndexes()
list_zipped = zip(list_idx, list_items)
for (index, item) in list_zipped:
    if not item.parent():  # if current item is exp
        data = self.mri_data[index.row()]
    else:  # if current item is ROI
        idx_parent = self.QTreeWidget.indexFromItem(item.parent())
        data = self.QTreeWidget[idx_parent.row()].ROIs[index.row()]

这有效,但是显然不是很好,我很确定它效率很低。那就是为什么我写这篇文章。我读到可以在QTreeWidgetItems中存储数据,但是在重写整个代码之前,我想问一下专家这是否是个好主意。如果存储的数据很大,我将找不到有关性能的任何信息(4d堆栈的大小高达256x256x32x2500,并且我同时在QTreeWidget中进行了数百个实验)。还是最好使用完全不同的数据库方法?不幸的是,(至少对我来说)很难找到有关类似问题的教程或帖子……也许是因为我使用了错误的关键词?!

预先感谢您的回答/提示/链接等

1 个答案:

答案 0 :(得分:0)

我测试了将数据存储在QTreeWidgetItems中很长时间的实现,至少在我看来,它的工作原理很吸引人。例如,添加新项目非常舒适:

def add_dataset(self, _obj):
    """adds new QTreeWidgetItem when 'addItemSignal' is emitted from ImportDataDialog"""
    tree_obj = QtWidgets.QTreeWidgetItem([_obj.name])
    tree_obj.setData(1, QtCore.Qt.UserRole, _obj)
    self.treeWidget.addTopLevelItem(tree_obj)

但是,对我而言,最好的方法是使用QDataStream保存/加载工作区的非常简单而优雅的方法:

def action_saveworkspace_triggered(self, filename):
    """Saves current workspace to the selected file"""
    file = QtCore.QFile(filename)
    file.open(QtCore.QIODevice.WriteOnly)
    datastream = QtCore.QDataStream(file)
    root_item = self.treeWidget.invisibleRootItem()

    # write the total number of items to be stored
    datastream.writeUInt32(root_item.childCount())

    # write all data (= all elements of the TreeWidget) to the file
    for n in range(root_item.childCount()):
        item = root_item.child(n)
        item.write(datastream)

我仍然不确定这是否是最有效的方法,但是至少对于我的应用程序,我不会遇到任何性能问题等。