Java 战列舰应用程序崩溃,如果我运行它通过主菜单后,光滑的开始

Java 战列舰应用程序崩溃,如果我运行它通过主菜单后,光滑的开始,java,swing,Java,Swing,我正在创建一个战舰游戏,有4个使用套接字的类。计算机、播放器消息和菜单类。为了开始游戏,我运行计算机类(服务器),然后运行菜单类(打开菜单)。通过菜单,我点击开始创建一个新的播放器对象,如下所示 public static void runPlayer() { Player client = new Player(); //creates player client.createBoard(); client.run(); } 如果我运行计算机类,然后运行玩家类

我正在创建一个战舰游戏,有4个使用套接字的类。计算机、播放器消息和菜单类。为了开始游戏,我运行计算机类(服务器),然后运行菜单类(打开菜单)。通过菜单,我点击开始创建一个新的播放器对象,如下所示

public static void runPlayer()
{
    Player client = new Player();   //creates player
    client.createBoard();
    client.run();


}
如果我运行计算机类,然后运行玩家类,那么游戏将成功运行。但是当我在菜单中调用runplayer方法时,会弹出一个没有任何内容的窗口

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EtchedBorder;
import sun.audio.*;

public class Menu  {
    private javax.swing.JLabel image;
    private static final int EXIT_ON_CLOSE = 0;
    JFrame frame = new JFrame();
    JPanel panel = new JPanel(new BorderLayout());
    JLabel statusbar = new JLabel(" Battleship");
    JLabel Battleship = new JLabel("          Battleship ");
    static AudioPlayer MGP = AudioPlayer.player;
    static AudioStream BGM;
    AudioData MD;

    static ContinuousAudioDataStream loop = null;
    public static void waiting (int n)
    {

        long t0, t1;

        t0 =  System.currentTimeMillis();

        do{
            t1 = System.currentTimeMillis();
        }
        while (t1 - t0 < n);
    }


    public Menu() 
    {

        frame.setTitle("Battleship");


        statusbar.setBorder(BorderFactory.createEtchedBorder(
                EtchedBorder.RAISED));
        Battleship.setBorder(BorderFactory.createEtchedBorder(
                EtchedBorder.RAISED));

        panel.setLayout(null);

        JButton start = new JButton("Start");
        start.setBounds(100, 660, 80, 25);


        JButton exit = new JButton("Exit");
        exit.setBounds(190, 660, 80, 25);

        JButton StopMusic = new JButton("Stop Music");
        StopMusic.setBounds(300, 660, 160, 25);

        JButton StartMusic = new JButton("Start Music");
        StartMusic.setBounds(470, 660, 160, 25);


        Battleship.setFont(new Font("Courier New", Font.ITALIC, 36));
        Battleship.setForeground(Color.BLACK);



        image = new javax.swing.JLabel();
        image.setIcon(new javax.swing.ImageIcon("./battleship2.jpg"));
        frame.add(image, BorderLayout.EAST);
        frame.pack();



        frame.add(start);
        frame.add(exit);
        frame.add(StopMusic);
        frame.add(StartMusic);


        frame.add(panel);
        frame.add(statusbar, BorderLayout.SOUTH);
        frame.add(Battleship, BorderLayout.NORTH );



        frame.setSize(700, 800);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setVisible(true);

        music();



        start.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent e)
            {

                {                           
                        frame.dispose();                //closes frame
                        stopMusic();                    //stops music
                        //waiting(500);
                        runPlayer();





            }}
         });
        StopMusic.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent e)
            {

                {                           
                    stopMusic();

                }
            }
         });
        StartMusic.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent e)
            {

                {                           
                    startMusic();

                }
            }
         });

       exit.addActionListener(new ActionListener() 
       {
        public void actionPerformed(ActionEvent e)
        {

            System.out.println( "Ending Game" );
            System.exit(0);
        }
     });}




    public static void music() 
    {       
        try
        {
            InputStream test = new FileInputStream("./battle.wav");
            BGM = new AudioStream(test);
            AudioPlayer.player.start(BGM);




        }
        catch(FileNotFoundException e){
            System.out.print(e.toString());
        }
        catch(IOException error)
        {
            System.out.print(error.toString());
        }
        MGP.start(loop);





    }
    public void stopMusic() 
    {
        if (BGM != null)
          AudioPlayer.player.stop(BGM);
        if (loop != null)
          AudioPlayer.player.stop(loop);
      }
    public void startMusic() {
        try
        {
            InputStream test = new FileInputStream("./battle.wav");
            BGM = new AudioStream(test);
            AudioPlayer.player.start(BGM);




        }
        catch(FileNotFoundException e){
            System.out.print(e.toString());
        }
        catch(IOException error)
        {
            System.out.print(error.toString());
        }
        MGP.start(loop);
      }
    public static void runPlayer()
    {
        Player client = new Player();   //creates player
        client.createBoard();
        client.run();


    }

    public static void main(String[] args) 
    {       
        new Menu();                       
    }
}

用提供的信息回答这个问题有点困难。但是我必须猜测runPlayer()方法在做什么。我假设其中存在某种类型的while循环,防止刷新您创建的新JFrame

尝试将stopMusic()和runPlayer()放在新线程中

基本上是这样的

start.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent e) {
    frame.dispose(); // closes frame

    new Thread(){
      public void run(){
        stopMusic(); // stops music
        runPlayer();
      }
    }.start();
  }
}); 

我认为问题不在你展示的代码范围之内;它可能是任何东西,从缺少的
setVisible()
到问题。FWIW,我对代码有一些观察:

  • 大卫·杨刚刚建议,在计算机上构建GUI

  • 使用静态常量以避免重复

  • 不要使用空格来设置标签的格式;使用
    JLabel
    校准常数

  • 不要使用空布局,而是使用嵌套布局来获得所需的结果

  • 为了避免在构造函数中调用公共方法,您复制了
    startMusic()
    的代码。相反,在构造函数完成后调用它

  • 下面是一个例子:

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.EventQueue;
    import java.awt.Font;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import javax.swing.BorderFactory;
    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.border.EtchedBorder;
    import sun.audio.*;
    
    public class Menu {
    
        private static final String TITLE = "Battleship";
        private static final String SOUND_FILE = "./battle.wav";
        private javax.swing.JLabel image;
        JFrame frame = new JFrame(TITLE);
        JPanel center = new JPanel(new BorderLayout());
        JLabel statusbar = new JLabel(TITLE);
        JLabel battleship = new JLabel(TITLE, JLabel.CENTER);
        static AudioPlayer MGP = AudioPlayer.player;
        static AudioStream BGM;
        static ContinuousAudioDataStream loop = null;
        AudioData MD;
    
        public Menu() {
    
            frame.setTitle("Battleship");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            statusbar.setBorder(BorderFactory.createEtchedBorder(
                EtchedBorder.RAISED));
            battleship.setBorder(BorderFactory.createEtchedBorder(
                EtchedBorder.RAISED));
    
            JButton start = new JButton("Start");
            JButton exit = new JButton("Exit");
            JButton StopMusic = new JButton("Stop Music");
            JButton StartMusic = new JButton("Start Music");
    
            battleship.setFont(new Font("Courier New", Font.ITALIC, 36));
            battleship.setForeground(Color.BLACK);
    
            image = new JLabel();
            image.setHorizontalAlignment(JLabel.CENTER);
            image.setIcon(new ImageIcon("./battleship2.jpg"));
            center.add(image, BorderLayout.CENTER);
    
            JPanel panel = new JPanel();
            panel.add(start);
            panel.add(exit);
            panel.add(StopMusic);
            panel.add(StartMusic);
            center.add(panel, BorderLayout.SOUTH);
    
            frame.add(battleship, BorderLayout.NORTH);
            frame.add(center, BorderLayout.CENTER);
            frame.add(statusbar, BorderLayout.SOUTH);
    
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
    
            start.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    //frame.dispose();
                    stopMusic();
                    runPlayer();
                }
            });
            StopMusic.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    stopMusic();
                }
            });
            StartMusic.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    startMusic();
                }
            });
    
            exit.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
    
                    System.out.println("Ending Game");
                    System.exit(0);
                }
            });
        }
    
        public void stopMusic() {
            if (BGM != null) {
                AudioPlayer.player.stop(BGM);
            }
            if (loop != null) {
                AudioPlayer.player.stop(loop);
            }
        }
    
        public void startMusic() {
            try {
                InputStream test = new FileInputStream(SOUND_FILE);
                BGM = new AudioStream(test);
                AudioPlayer.player.start(BGM);
                MGP.start(loop);
            } catch (FileNotFoundException e) {
                System.out.print(e.toString());
            } catch (IOException error) {
                System.out.print(error.toString());
            }
        }
    
        public static void runPlayer() {
            Player client = new Player();
            client.createBoard();
            client.run();
        }
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    Menu menu = new Menu();
                    menu.startMusic();
                }
            });
        }
    
        // stub for missing class
        private static class Player {
            void createBoard() {}
            void run() {}
        }
    }
    

    一个旁注。我会把你们所有的听众浓缩成一个单元。ActionListener al=新ActionListener(){};向该操作侦听器注册所有按钮,然后在侦听器内部检查源代码。如果(e.getSource==start){//Do start things..etc.}你是说如果你使用计算机,那么播放器在没有菜单的情况下运行良好。然后你说如果你只是从菜单上运行播放器,它就不工作了。如果从菜单中运行计算机然后运行播放机,它是否工作?计算机和播放器是如何耦合的。如果它们是相同的,那么它们的初始化有什么不同呢?我强烈建议不要将一个ActionListener用于多种用途。这就产生了高耦合和低内聚,因为现在一堆不相关的事情都在一起处理。在我看来,我认为将同一类中性质类似的动作侦听器捆绑在一起可以提高内聚性,并大大提高代码的可读性。它们在所执行的任务中并不相关,但在它们所代表的内容(即由其菜单执行的操作)中是相关的。由于Java还没有闭包(直到Java 7),匿名类通常是事件处理的最佳选择。它更详细,但对未来的代码维护者来说更清晰。还有其他原因,如执行路径等。大型开关,if/else if也会增加圈复杂度。
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.EventQueue;
    import java.awt.Font;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import javax.swing.BorderFactory;
    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.border.EtchedBorder;
    import sun.audio.*;
    
    public class Menu {
    
        private static final String TITLE = "Battleship";
        private static final String SOUND_FILE = "./battle.wav";
        private javax.swing.JLabel image;
        JFrame frame = new JFrame(TITLE);
        JPanel center = new JPanel(new BorderLayout());
        JLabel statusbar = new JLabel(TITLE);
        JLabel battleship = new JLabel(TITLE, JLabel.CENTER);
        static AudioPlayer MGP = AudioPlayer.player;
        static AudioStream BGM;
        static ContinuousAudioDataStream loop = null;
        AudioData MD;
    
        public Menu() {
    
            frame.setTitle("Battleship");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            statusbar.setBorder(BorderFactory.createEtchedBorder(
                EtchedBorder.RAISED));
            battleship.setBorder(BorderFactory.createEtchedBorder(
                EtchedBorder.RAISED));
    
            JButton start = new JButton("Start");
            JButton exit = new JButton("Exit");
            JButton StopMusic = new JButton("Stop Music");
            JButton StartMusic = new JButton("Start Music");
    
            battleship.setFont(new Font("Courier New", Font.ITALIC, 36));
            battleship.setForeground(Color.BLACK);
    
            image = new JLabel();
            image.setHorizontalAlignment(JLabel.CENTER);
            image.setIcon(new ImageIcon("./battleship2.jpg"));
            center.add(image, BorderLayout.CENTER);
    
            JPanel panel = new JPanel();
            panel.add(start);
            panel.add(exit);
            panel.add(StopMusic);
            panel.add(StartMusic);
            center.add(panel, BorderLayout.SOUTH);
    
            frame.add(battleship, BorderLayout.NORTH);
            frame.add(center, BorderLayout.CENTER);
            frame.add(statusbar, BorderLayout.SOUTH);
    
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
    
            start.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    //frame.dispose();
                    stopMusic();
                    runPlayer();
                }
            });
            StopMusic.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    stopMusic();
                }
            });
            StartMusic.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    startMusic();
                }
            });
    
            exit.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
    
                    System.out.println("Ending Game");
                    System.exit(0);
                }
            });
        }
    
        public void stopMusic() {
            if (BGM != null) {
                AudioPlayer.player.stop(BGM);
            }
            if (loop != null) {
                AudioPlayer.player.stop(loop);
            }
        }
    
        public void startMusic() {
            try {
                InputStream test = new FileInputStream(SOUND_FILE);
                BGM = new AudioStream(test);
                AudioPlayer.player.start(BGM);
                MGP.start(loop);
            } catch (FileNotFoundException e) {
                System.out.print(e.toString());
            } catch (IOException error) {
                System.out.print(error.toString());
            }
        }
    
        public static void runPlayer() {
            Player client = new Player();
            client.createBoard();
            client.run();
        }
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    Menu menu = new Menu();
                    menu.startMusic();
                }
            });
        }
    
        // stub for missing class
        private static class Player {
            void createBoard() {}
            void run() {}
        }
    }