从文本文件填充UI - python

时间:2015-12-11 20:45:56

标签: python pyside

我把问题分解为一个非常基本的设置。每个选项卡允许用户单击按钮并将项目追加到列表中。在将项目添加到列表的同时,它还会添加到名为 ALLITEMs 的全局变量中。每个标签都会在字典上显示,以便附加到此处。

ALLITEMS = {
        "A" : [],
        "B" : []
    }

在' closeEvent '的主要小部件中我将此变量保存到json文件。同样在主要小部件' showEvent '我将这些数据加载到全球可控的 ALLITEMS 中。这允许用户在每次启动应用程序时保留数据。我不确定的是如何刷新选项卡小部件以使用变量中的数据重新填充GUI。但只有在最初启动该工具时。我不希望每次用户点击该标签时都加载它,这会产生重复的数据。

enter image description here

import sys
import json
import os
from PySide import QtGui, QtCore

ALLITEMS = {
    "A" : [],
    "B" : []
}

# Widgets
# ------------------------------------------------------------------------------
class ExampleA(QtGui.QWidget):

    def __init__(self):
        super(ExampleA, self).__init__()
        self.initUI()

    def initUI(self):      
        # formatting
        self.resize(550, 400)
        self.setWindowTitle("Tab A")

        # widgets
        self.ui_listview = QtGui.QListWidget()
        self.ui_add = QtGui.QPushButton("Add Item")

        # signals
        self.ui_add.clicked.connect(self.add_item_clicked)

        # main layout
        main_layout = QtGui.QVBoxLayout()
        main_layout.addWidget(self.ui_add)
        main_layout.addWidget(self.ui_listview)
        main_layout.setContentsMargins(0,0,0,0)
        self.setLayout(main_layout)

    def add_item_clicked(self):
        global ALLITEMS
        item = "Another item A"
        ALLITEMS["A"].append(item)
        self.ui_listview.addItem( item )


class ExampleB(QtGui.QWidget):

    def __init__(self):
        super(ExampleB, self).__init__()
        self.initUI()

    def initUI(self):      
        # formatting
        self.resize(550, 400)
        self.setWindowTitle("Tab A")

        # widgets
        self.ui_listview = QtGui.QListWidget()
        self.ui_add = QtGui.QPushButton("Add Item")

        # signals
        self.ui_add.clicked.connect(self.add_item_clicked)

        # main layout
        main_layout = QtGui.QVBoxLayout()
        main_layout.addWidget(self.ui_add)
        main_layout.addWidget(self.ui_listview)
        main_layout.setContentsMargins(0,0,0,0)
        self.setLayout(main_layout)

    def add_item_clicked(self):
        global ALLITEMS
        item = "Another item B"
        ALLITEMS["B"].append(item)
        self.ui_listview.addItem( item )


class ExampleMain(QtGui.QWidget):

    def __init__(self):
        super(ExampleMain, self).__init__()
        self.initUI()

    def initUI(self):      
        # formatting
        self.resize(200, 200)
        self.setWindowTitle("Test")

        # widgets
        tab_panel = QtGui.QTabWidget()
        tab_panel.addTab(ExampleA(), "Tab A")
        tab_panel.addTab(ExampleB(), "Tab B")

        # main layout
        main_layout = QtGui.QVBoxLayout()
        main_layout.addWidget(tab_panel)
        main_layout.setContentsMargins(0,0,0,0)
        self.setLayout(main_layout)

    def closeEvent(self, event):
        self.save_data()

    def showEvent(self, event):
        self.load_data()

    def save_data(self):
        print "Saving..."
        global ALLITEMS
        json.dump(ALLITEMS, open("Example_Data.json",'w'), indent=4)

    def load_data(self):
        global ALLITEMS
        if os.path.exists( "Example_Data.json" ):
            with open( "Example_Data.json" ) as f:
                data = json.load(f)
                ALLITEMS = data

# Main
# ------------------------------------------------------------------------------
if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    ex = ExampleMain()
    ex.show()
    sys.exit(app.exec_())

2 个答案:

答案 0 :(得分:1)

我会完全删除全局变量。

在closeEvent中,不是保存全局变量,而是直接从listview中读取项目并保存它们。在add_item方法中,根本不要修改全局变量。

然后在您的load_data函数中,从文件中读取数据并将项目添加到列表视图中。

您需要存储对ex.ample小部件的引用

self.example_a = ExampleA()
self.example_b = ExampleB()

tab_panel.addTab(self.example_a), "Tab A")
tab_panel.addTab(self.example_b), "Tab B")

以下是保存和加载数据的方法:

def save_data(self):
    print "Saving..."
    all_items = {}
    for i in range(self.example_a.ui_listview.count()):
        text = self.example_a.ui_listview.item(i).text()
        all_items.set_default('A', []).append(text)
    for i in range(self.example_b.ui_listview.count()):
        text = self.example_b.ui_listview.item(i).text()
        all_items.set_default('B', []).append(text)
    json.dump(all_items, open("Example_Data.json",'w'), indent=4)

def load_data(self):
    if os.path.exists( "Example_Data.json" ):
        with open( "Example_Data.json" ) as f:
            all_items = json.load(f)
            for text in all_items.get('A', []):
                self.example_a.ui_listview.addItem(text)
            for text in all_items.get('B', []):
                self.example_b.ui_listview.addItem(text)

此外,通常,父窗口小部件直接访问孙窗口小部件通常是不好的设计(ui_listview是主要窗口小部件ExampleMain类的孙子)。对于您的小部件来说,通常更好的形式是定义某种类型的界面来描绘他们需要保存和加载的内容。

class ExampleMain:

    def save_data(self):
        data = {}
        data['example_a'] = self.example_a.save_data()
        data['example_b'] = self.example_b.save_data()
        # Save to file

    def load_data(self):
        data = ... # read from file
        self.example_a.load_data(data.get('example_a'))
        self.example_b.load_data(data.get('example_b'))


class ExampleA:

    def save_data(self):
        data = []
        for i in range(self.ui_listview.count()):
            text = self.ui_listview.item(i).text()
            data.append(text)
        return data

    def load_data(self, data):
        for text in data:
            self.ui_listview.addItem(text)

答案 1 :(得分:1)

最简单(尽管不是很有效)的方法是每次更改时都从ALLITEMS字典更新列表小部件。因此,在按下每个按钮时,您可以先更新ALLITEMS,然后清除列表小部件的内容并根据ALLITEMS的新值重新填充[" TabName"]。然后在show事件上你也可以这样做 - 从文件一次加载ALLITEMS,然后更新列表小部件。

有关更有效的方法,请查看Qt模型/视图编程(http://doc.qt.io/qt-5/model-view-programming.html)您可能需要将QListWidget替换为QListView