使用二进制序列化加载菜单

loading menu with binary serialization

我在 java 中做海战游戏,我用 JMenubar 创建了一个菜单,我希望能够保存和加载游戏。

我创建了一个 class chargerActionListener 来实现 ActionListener 将它添加到我的菜单中的项目但它不起作用,这对我来说不是 return 错误,但不会加载 plateau 对象,我的加载函数是正确,我测试过。

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

}

我很快写了这段代码,它工作得很好,但同样的问题。 我有三个按钮;一个是在控制台中保存、加载和显示人体对象,我可以放心保存。 例如 :我用 human ("jean", 10) 启动程序(在主函数中) 我保存。 我退出我的程序并改变 人类("jean"、50) 当我按下加载按钮时 我加载我之前保存的文件 然后我点击按钮在控制台中显示它会显示我 "Human [jean, 50]" 但我想要 "Human [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");

您的序列化代码工作正常。您的问题在于如何显示获得的结果。你这样做:

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); 调用是指传递给构造函数的参数,而不是 class 的字段,因此该值永远不会改变。

如果您现在将代码更改为:

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

        // ....
    }

    // ....
}

由于getHuman()returns实例字段所持有的值,human,你会看到结果是正确的,human字段的参考值实际上已经改变了。

您的问题出在与 display JButton 关联的 actionListener() 方法中。因为 class 成员 human 与 class Fenetre 的构造函数中的参数具有相同的名称,所以在构造函数代码中任何你想访问成员的地方(而不是参数)您需要使用 this 关键字对其进行限定。

方法actionListener()的写法如下:

display.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent evenement) {
        System.out.println(Fenetre.this.human);
    }
});

您需要 Fenetre.this.human,因为您正在创建一个匿名的内部 class 并且 human 是封闭 class.

的成员

如果您至少使用 Java 8,则可以将匿名的内部 class 替换为 lambda expression,因为接口 java.awt.event.ActionListener 是功能接口,即一个只包含一个抽象方法的接口。这是替换匿名内部 class.

的 lambda 表达式
display.addActionListener(e -> System.out.println(this.human));

如你所见,在lambda表达式中你只需要写this.human就可以访问class Fenetre.[=25的成员human =]