我是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 按钮会消失。另一方面,保存按钮已重新粉刷:变为粉红色并获取正确加载的文本字段内容。
所以我的问题是:如何正确保存已保存的表单并防止按钮消失?
答案 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);
}