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



我是一个Java新手,我正在做我的第一个Java项目。到目前为止,它由一个带有动态生成表单(改编自此问题)、一个保存按钮和一个加载按钮的 GUI 组成。使用"保存"按钮,整个表单将另存为对象,使用"加载"按钮,可以加载现有的已保存表单。保存和加载本身似乎有效,但是在我(间接地,即通过另一个函数)调用revalidate()并在加载按钮的actionPerformed方法中repaint()时,GUI 没有使用加载的表单正确更新:

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;
}
}

在这里,panelJPanel的子类:

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();
}
}

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

public class Entry extends JPanel implements Serializable{
private static final long serialVersionUID = 8748191176188997955L;
private JTextField textField;
private JButton plus;
private JButton minus;
private EntryList parent;
public Entry(String textFieldText, EntryList list) {
this.parent = list;
this.plus = new JButton(new AddEntryAction());
this.minus = new JButton(new RemoveEntryAction());
this.textField = new JTextField(10);
this.textField.setText(textFieldText);
add(this.plus);
add(this.minus);
add(this.textField);
}
public String getText() {
return this.textField.getText();
}
public class AddEntryAction extends AbstractAction {
private static final long serialVersionUID = -1936452299010320790L;
public AddEntryAction() {
super("+");
}
public void actionPerformed(ActionEvent e) {
parent.cloneEntry(Entry.this);
}
}
public class RemoveEntryAction extends AbstractAction {
private static final long serialVersionUID = 4843871176230776949L;
public RemoveEntryAction() {
super("-");
}
public void actionPerformed(ActionEvent e) {
parent.removeItem(Entry.this);
}
}
public void enableAdd(boolean enabled) {
this.plus.setEnabled(enabled);
}
public void enableMinus(boolean enabled) {
this.minus.setEnabled(enabled);
}
}

public class EntryList extends JPanel implements Serializable{
private static final long serialVersionUID = 1426379083556312697L;
private List<Entry> entries;
public EntryList() {
this.entries = new ArrayList<Entry>();
Entry initial = new Entry("debugtext", this);
addItem(initial);
}
public int getLength() {
return this.entries.size();
}
public String getFirstText() {
return this.entries.get(0).getText();
}
public void cloneEntry(Entry entry) {
Entry theClone = new Entry("", this);
addItem(theClone);
}
private void addItem(Entry entry) {
entries.add(entry);
add(entry);
refresh();
}
public void removeItem(Entry entry) {
entries.remove(entry);
remove(entry);
refresh();
}
private void refresh() {
revalidate();
if (entries.size() == 1) {
entries.get(0).enableMinus(false);
}
else {
for (Entry e : entries) {
e.enableMinus(true);
}
}
}
}
public class SaveListener extends DirectoryChooser implements ActionListener {
private static final long serialVersionUID = -8842006866700189526L;
private EntryList list;
private String filename;
public SaveListener(String choosertitle, ScrollBar bar) {
super(choosertitle, false);
this.list = bar.getEntryList();
}
@Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
try {
filename = this.getResultsDirectory();
OutputStream os = new FileOutputStream(filename);
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(list);
oos.close();
System.out.println("Length of list at saving = " + this.list.getLength());
System.out.println("Length of list at saving = " + this.list.getFirstText());
} catch (FileNotFoundException e1) {
System.out.println("File not found: " + filename);
e1.printStackTrace();
} catch (IOException e1) {
System.out.println("IO Exception: " + e1);
e1.printStackTrace();
}
}
}
public class DirectoryChooser extends JPanel implements ActionListener {
private static final long serialVersionUID = -8143869075088499054L;
private JButton setwd;
private String workingdir;
private JFileChooser chooser;
private String choosertitle;
private boolean directoryOnly = true;
@SuppressWarnings("hiding")
public DirectoryChooser(String choosertitle) {
this.choosertitle = choosertitle;
setwd = new JButton(choosertitle);
setwd.addActionListener(this);
add(setwd);
workingdir = new File(System.getProperty("user.dir")).toString();
}
@SuppressWarnings("hiding")
public DirectoryChooser(String choosertitle, boolean directoryOnly) {
this(choosertitle);
this.directoryOnly = directoryOnly;
}
public void actionPerformed(ActionEvent e) {    
chooser = new JFileChooser(); 
chooser.setCurrentDirectory(new java.io.File("."));
chooser.setDialogTitle(choosertitle);
if (directoryOnly) {
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
}
chooser.setAcceptAllFileFilterUsed(false);
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { 
workingdir = chooser.getSelectedFile().toString();
} else {
workingdir = chooser.getCurrentDirectory().toString();
}
}
public String getResultsDirectory() {
return workingdir;
}
public Dimension getPreferredSize(){
return new Dimension(200, 200);
}
}
public class SingleFileChooser extends JPanel implements ActionListener {
private static final long serialVersionUID = -9068219101747975546L;
private JButton loadFiles;
private JFileChooser chooser;
private String choosertitle;
private File file;
private String filePath;
private FileNameExtensionFilter filter; 
@SuppressWarnings("hiding")
public SingleFileChooser(String choosertitle) {
this.choosertitle = choosertitle;
loadFiles = new JButton(choosertitle);
loadFiles.addActionListener(this);
add(loadFiles);
}
@SuppressWarnings("hiding")
public SingleFileChooser(String choosertitle, FileNameExtensionFilter filter) {
this(choosertitle);
this.filter = filter;
}
public void actionPerformed(ActionEvent e) {    
chooser = new JFileChooser(); 
chooser.setMultiSelectionEnabled(false);
if (filter != null) {
chooser.setFileFilter(filter);
}
chooser.setDialogTitle(choosertitle);
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);

int returnVal = chooser.showOpenDialog(null);
if(returnVal == JFileChooser.APPROVE_OPTION) {
file = chooser.getSelectedFile();
filePath = file.getAbsolutePath();
}
}
public File getFile() {
return file;
}
public String getFilePath(){
return filePath;
}
public Dimension getPreferredSize(){
return new Dimension(200, 200);
}
}
public class MainFrame extends JFrame {
private static final long serialVersionUID = 512941639567306317L;
EntryList panel = new EntryList();
ScrollBar scrollPanel = new ScrollBar(panel, this);
public MainFrame() throws HeadlessException {   
this.getContentPane().add(scrollPanel);
this.setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS));
}
}
public class GUImain {
public static void main(String[] args) {
MainFrame frame = new MainFrame();
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null); // center the window
}
}

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

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

序列化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);
}

最新更新