我正在用java做一个海战游戏,我用JMenubar创建了一个菜单,我希望能够保存和加载一个游戏。
我创建了一个类 chargerActionListener 实现ActionListener将其添加到我的菜单中的一个项目中,但它不工作,这不会给我返回一个错误,但不会加载 高原 对象,我的加载功能是正确的,我测试了它。
package actionlistener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.JFileChooser;
import Main.Plateau;
import interfaceGraphique.Fenetre;
import ioforme.IOPlateau;
public class ChargerActionListener implements ActionListener {
public Fenetre fenetre;
public Plateau plateau;
public ChargerActionListener(Fenetre fenetre)
{
this.fenetre = fenetre;
}
public void actionPerformed(ActionEvent arg0) {
JFileChooser choix = new JFileChooser();
int retour=choix.showOpenDialog(fenetre);
if(retour==JFileChooser.APPROVE_OPTION){
try {
Plateau p = IOPlateau.lire(choix.getSelectedFile().getAbsolutePath());
fenetre.setPlateau(p);
System.out.println(choix.getSelectedFile().getAbsolutePath());
fenetre.actualiserGrilleCible();
fenetre.actualiserMaGrille();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
我很快就写了这段代码,它工作得很完美,但问题还是一样的,我有三个按钮,一个是保存,一个是加载,还有一个是在控制台显示人类对象,我可以放心地保存。例如 : 我启动了这个程序 人类("让",10) (在主函数中)我保存.我退出我的程序,然后我改变了人类("让",50) 当我按下加载按钮时,我加载了之前保存的文件,然后我点击按钮,在控制台显示,它会显示我 "人类[Jean,50]",但我想 "人类[Jean,10]"
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import javax.swing.*;
public class Main {
public static class Human implements Serializable {
String name;
int age;
public Human(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String toString() {
return "Human [name=" + name + ", age=" + age + "]";
}
}
public static class ChargerActionListener implements ActionListener {
public Fenetre fenetre;
public ChargerActionListener(Fenetre fenetre)
{
this.fenetre = fenetre;
}
public void actionPerformed(ActionEvent arg0) {
JFileChooser choix = new JFileChooser();
int retour=choix.showOpenDialog(null);
if(retour==JFileChooser.APPROVE_OPTION){
try {
Human h = IOPlateau.lire(choix.getSelectedFile().getAbsolutePath());
fenetre.setHuman(h);
System.out.println(choix.getSelectedFile().getAbsolutePath());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static class SauvegarderActionListener implements ActionListener {
public Fenetre fenetre;
public SauvegarderActionListener(Fenetre fenetre)
{
this.fenetre = fenetre;
}
public void actionPerformed(ActionEvent arg0) {
JFileChooser choix = new JFileChooser();
int retour=choix.showSaveDialog(null);
if(retour==JFileChooser.APPROVE_OPTION){
try {
IOPlateau.sauver(fenetre.getHuman(),choix.getSelectedFile().getAbsolutePath());
System.out.println(choix.getSelectedFile().getAbsolutePath());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static class Fenetre extends JFrame {
private Human human;
Fenetre (Human human)
{
this.human = human;
this.setTitle("test");
this.setSize(1200,500);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton save = new JButton ();
save.addActionListener(new SauvegarderActionListener(this));
JButton load = new JButton();
load.addActionListener(new ChargerActionListener(this));
JButton display = new JButton ();
JPanel panel = new JPanel (new GridLayout(1,3));
// Button for load and save !
panel.add(save);
panel.add(load);
panel.add(display);
this.setContentPane(panel);
display.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evenement)
{
System.out.println(human);
}
});
this.setVisible(true);
}
public void setHuman (Human human)
{
this.human = human;
}
public Human getHuman ()
{
return this.human;
}
}
public static class IOPlateau {
public static Human lire(String fileName) throws IOException {
Human h = null;
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName));
try {
h = (Human) ois.readObject();
} catch (ClassNotFoundException cnfe) {
// erreur de lecture
} catch (EOFException eofe) {
//fin de fichier
}
ois.close();
return h;
}
public static void sauver(Human h, String fileName) throws IOException {
try {
// Recevoir le fichier
File f = new File(fileName);
// Créer un nouveau fichier
// Vérifier s'il n'existe pas
if (f.createNewFile())
System.out.println("File created");
else
System.out.println("File already exists");
}
catch (Exception e) {
System.err.println(e);
}
ObjectOutputStream oos;
oos = new ObjectOutputStream(new FileOutputStream(fileName));
oos.writeObject(h);
oos.close();
}
}
public static void main(String[] args) {
Human human = new Human ("Jean",11);
Fenetre fenetre = new Fenetre(human);
}
}
你是否将ChargerActionListener正确地添加到项目中。
.addActionListener(new ChargerActionListener(fenetre));
也可以尝试使用:
JFileChooser jfc = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
int returnValue = jfc.showOpenDialog(null);
也许'null'作为'showOpenDialog'的参数会有效果(我不知道fenetre或plateau应该是什么)
另外,可能只有对话框打不开,但实际上Listener被调用了。
请通过运行类似(在'actionPerformed'中)的东西来检查。
System.out.println("Ok");
你的问题出在 actionListener()
的相关方法。展示 JButton
. 因为该类成员 human
与类的构造函数中的参数名称相同。Fenetre
在构造函数代码中,凡是要访问成员(而不是参数)的地方,都需要使用 this
关键字。
下面是方法 actionListener()
应该写。
display.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evenement) {
System.out.println(Fenetre.this.human);
}
});
你需要 Fenetre.this.human
因为你正在创建一个匿名的、内部的类和 human
是外层类的成员。
如果你使用的是至少Java 8,你可以将匿名的内类替换成一个 兰姆达表达式 由于接口 java.awt.event.ActionListener
是一个功能接口,即一个正好包含一个抽象方法的接口。这里是替换匿名、内类的lambda表达式。
display.addActionListener(e -> System.out.println(this.human));
正如你所看到的,在lambda表达式中,你只需要写上 this.human
为了进入会员 human
级别的 Fenetre
.
你的序列化代码工作正常。你的问题在于如何显示得到的结果。你可以这样做。
public static class Fenetre extends JFrame {
private Human human;
Fenetre(Human human) {
this.human = human;
// ....
display.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evenement) {
System.out.println(human);
}
});
// ....
}
// ....
}
你的 System.out.println(human);
调用的是传递到构造函数中的参数,而不是类的字段,所以值永远不会改变。
如果你现在把你的代码改成
public static class Fenetre extends JFrame {
private Human human;
Fenetre(Human human) {
this.human = human;
// ....
display.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evenement) {
System.out.println(getHuman());
}
});
// ....
}
// ....
}
Since getHuman()
返回实例字段human所持有的值,你会看到结果是正确的,human字段的引用值实际上已经改变了。