从文件系统加载对象后更新GUI

时间:2019-03-19 15:50:10

标签: java swing serialization

我是Java新手,正在从事我的第一个Java项目。到目前为止,它由一个具有动态生成形式的GUI(改编自this question),一个 Save 按钮和一个 Load 按钮组成。使用保存按钮,将整个表单另存为一个对象,使用 Load 按钮,可以加载现有的已保存表单。保存和加载本身似乎可以正常工作,但是在我(间接地,即通过另一个函数)在{{1}中调用revalidate()repaint()的时候,GUI无法用加载的表单正确更新。 } Load 按钮的方法:

actionPerformed

此处,public class LoadListener extends SingleFileChooser implements ActionListener { private static final long serialVersionUID = -4418195536438874952L; private EntryList listFromFile; private ScrollBar panel; @SuppressWarnings("hiding") public LoadListener(String choosertitle, ScrollBar panel) { super(choosertitle); this.panel = panel; } @Override public void actionPerformed(ActionEvent e) { super.actionPerformed(e); try { InputStream is = new FileInputStream(this.getFilePath()); ObjectInputStream ois = new ObjectInputStream(is); listFromFile = (EntryList) ois.readObject(); ois.close(); panel.setEntryList(listFromFile); } catch (FileNotFoundException e1) { System.out.println("File not found: " + this.getFilePath()); e1.printStackTrace(); } catch (IOException e1) { System.out.println("IO exception: " + this.getFilePath()); e1.printStackTrace(); } catch (ClassNotFoundException e1) { System.out.println("Class for input object not found: " + this.getFilePath()); e1.printStackTrace(); } } public EntryList getLoadedGatingList() { return listFromFile; } } panel的子类:

JPanel

下面列出了运行该示例所需的其余类:

public class ScrollBar extends JPanel {

    private static final long serialVersionUID = -3460555902426579496L;
    private JScrollPane scrollPane;
    private JButton saveList, loadList;
    private EntryList entryList;

    @SuppressWarnings("hiding")
    public ScrollBar(EntryList entryList, MainFrame frame) {
        scrollPane = new JScrollPane(entryList,
                ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        scrollPane.setPreferredSize(new Dimension(300,400));        
        this.entryList = entryList;
        saveList = new JButton("Save List");
        saveList.addActionListener(new SaveListener("Save List", this));
        loadList = new JButton("Load List");
        loadList.addActionListener(new LoadListener("Load List", this));
        add(scrollPane);
        add(saveList);
        add(loadList);
    }

    public EntryList getEntryList() {
        return entryList;
    }

    public void setEntryList(EntryList list) {
        entryList = list;
        this.saveList.setBackground(Color.PINK);
        this.saveList.setText(entryList.getFirstText());
        this.loadList.setBackground(Color.GREEN);
        revalidate();
        repaint();
    }
}

当我执行此代码时,请修改文本字段中的文本,保存表单并再次加载,保存的文本不会加载到文本字段中,并且 Load 按钮会消失。另一方面,保存按钮已重新粉刷:变为粉红色并获取正确加载的文本字段内容。

所以我的问题是:如何正确保存已保存的表单并防止按钮消失?

1 个答案:

答案 0 :(得分:1)

对AWT组件进行序列化不是一个好主意,原因有几个,其中之一就是与将来的发行版兼容。另一个是并非所有的swing对象都实现可序列化。例如GridLayout不可序列化。
存储重建和EntryList对象所需的所有信息,并在需要重建时使用它,应该更加简单。
重构Entry仅需要一个String,所以我建议将所有这些字符串存储在文件中,而不是尝试将EntryList对象保存到文件中。
在检索了每个代表一个Entry的字符串之后,您可以轻松地重建一个EntryList

添加一种将Entry添加到EntryList的方法:

public void addItem(String text) {
    Entry entry = new Entry(text, this);
    entries.add(entry);
    add(entry);
}

当您要重构EntryList时:

    //get all stored Entry strings from file into a List (for example) 
    List<String>entriesText = getEntriesStringsFromFile(); 

    EntryList eList = new EntryList(); //make a new EntryList 
    for (String text : entriesText){ //add all content to EntryList
        eList.addItem(text);
    }

现在您已经完全重建了EntryList
考虑向List<String>entriesText添加一个接受EntryList的构造函数。


旁注:我认为cloneEntry应该是:

public void cloneEntry(Entry entry) {
    Entry theClone = new Entry(entry.getText(), this);
    addItem(theClone);
}