Java &引用;“鬼实例”;在爪哇?

Java &引用;“鬼实例”;在爪哇?,java,swing,design-patterns,awt,instances,Java,Swing,Design Patterns,Awt,Instances,我在处理不同对象的实例时遇到问题,情况就是这样: 我已经用Java开发了一个小游戏(Swing&AWT)有一段时间了,我有以下课程: App.java Play.java Event.java GameSecene.java MenuScene.java Timer.java 其中: App扩展了JFrame,是一个具有应用程序主功能(main)的框架,此类创建游戏窗口,并且只存在这个JFrame MenuScene和GameSecene类是应用程序的场景,例如,当您看到菜单并希望看到最高

我在处理不同对象的实例时遇到问题,情况就是这样:

我已经用Java开发了一个小游戏(Swing&AWT)有一段时间了,我有以下课程:

  • App.java
  • Play.java
  • Event.java
  • GameSecene.java
  • MenuScene.java
  • Timer.java
其中:

  • App扩展了JFrame,是一个具有应用程序主功能(main)的框架,此类创建游戏窗口,并且只存在这个JFrame

  • MenuScene和GameSecene类是应用程序的场景,例如,当您看到菜单并希望看到最高分数时,它是一个场景,游戏级别是一个场景,等等,但在本例中,我只有两个场景,我在JPanel中表示了它们:MenuScene扩展了JPanel并创建了游戏菜单(按钮、图像等),同样适用于GameSecene类,这也扩展了JPanel并创建了游戏

  • 其他类(Play、Event、Timer)是简单类,它们具有“游戏逻辑”、键盘控制、计时器、游戏操作,并在GameSecene类的三个全局变量中实例化

一切都从App开始,创建它的一个实例,并在其构造函数中调用一个方法来“创建”菜单(MenuScene.java)。现在,菜单上有一个jb按钮,当按下该按钮时,“创建”游戏(GameScene.java)这个类有一个按钮可以随时返回菜单…在这里我遇到了问题,因为如果我在玩,我返回菜单的游戏仍然存在,我可能会失败,这是没有意义的,就像你在玩,但你看到的不是游戏的菜单,有趣的是,图形部分工作得很好,如果我按下一个按钮它会删除我拥有的内容并快速绘制我想要的场景。这是因为如果我没有弄错的话,播放、计时器和事件会被实例化或“存在”在内存中。因此如果我再次按下“创建游戏”JButton我会重新创建第二个GameSecene实例?对于MenuScene和GameSecene来说是无限的。有解决方案吗?你认为我应该如何构造应用程序

我给大家介绍一下最重要的课程:

App.java

public class App extends JFrame {
   private JPanel rootPanel;

   public App() {
      //Define frame
      ...
      runScene(new MenuScene(this));
   }

   public void runScene(JPanel scene) {
      destroyScene();

      rootPanel.setBackground(scene.getBackground());
      rootPanel.add(scene);
      rootPane.validate();
      rootPanel.repaint();
   }

   private void destroyScene() {
      rootPanel.removeAll();
      rootPanel.revalidate();
      rootPanel.repaint();
   }


   public static void main(String[] args) { //Main
      new App();
   }
}
public class MenuScene extends JPanel {
   private App app;

   public MenuScene(App app) {
      this.app = app;
      //Define JPanel
      ...
      buttonStart.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            app.runScene(new GameScene(app));
        }
      });
   }
}
public class GameScene extends JPanel {
   private App;
   private Play;
   private Timer;
   private Event; //Define controls (keyboard)

   public GameScene(App app) {
      this.app = app;
      //Define JPanel, Play, Timer and Event
      ...
      buttonBackMenu.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            app.runScene(new MenuScene(app));
        }
      });
   }
}
public class Play {
   private JLabel[][] x;

   public Play(JLabel[][] x) { //This matrix is important (is an reference), is instanced in GameScene, this is an problem?
      this.x = x;
      //Define others variables
   }
}
   public class App extends JFrame {
       private JPanel rootPanel;
       private static App app;

       private App() {
          super("x");
          createApp();
       }

       public static App getInstance() {
          if (app == null) {
            app = new App();
          }

          return app;
       }

       private void createApp() {
         //Define JFrame, rootPanel, buttons, etc ...
       }

       public void runScene(JPanel scene) {
          rootPanel.removeAll();

          rootPanel.add(scene);
          rootPanel.revalidate();
          rootPanel.repaint();
       }

       public static void main(String[] args) { //Main
          getInstance().runScene(new MenuScene());
       }
    }
    public class GameScene extends JPanel {

    private Play p;
    private Timer t;
    private Event e; //Define controls (keyboard)
    private JLabel[][] mat;

    public GameScene() {
       //Define JPanel, Matrix, Play, Timer and Event
       ...
       buttonBackMenu.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent x) {
             This method is useful to create another scene for example from another instance other than this (GameScene)
             changeScene(new MenuScene());
         }
       });
    }

    public void changeScene(JPanel scene) {
        e.removeKeyDispatcher(); //You must create a method that allows you to move the event key dispatcher
        t.stopAllTimers(); //You must create a method to stop all timers, or any object that is active.
        t = null;
        e = null;
        p = null;
        //If you have more active objects and work with other instances of other classes they should be "broken" or "stopped" and then match their instance to null
        App.getInstance().runScene(scene);
    }

    //Optional...
    public JLabel[][] getMat() {
       return mat;
    }
 }
MenuScene.java

public class App extends JFrame {
   private JPanel rootPanel;

   public App() {
      //Define frame
      ...
      runScene(new MenuScene(this));
   }

   public void runScene(JPanel scene) {
      destroyScene();

      rootPanel.setBackground(scene.getBackground());
      rootPanel.add(scene);
      rootPane.validate();
      rootPanel.repaint();
   }

   private void destroyScene() {
      rootPanel.removeAll();
      rootPanel.revalidate();
      rootPanel.repaint();
   }


   public static void main(String[] args) { //Main
      new App();
   }
}
public class MenuScene extends JPanel {
   private App app;

   public MenuScene(App app) {
      this.app = app;
      //Define JPanel
      ...
      buttonStart.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            app.runScene(new GameScene(app));
        }
      });
   }
}
public class GameScene extends JPanel {
   private App;
   private Play;
   private Timer;
   private Event; //Define controls (keyboard)

   public GameScene(App app) {
      this.app = app;
      //Define JPanel, Play, Timer and Event
      ...
      buttonBackMenu.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            app.runScene(new MenuScene(app));
        }
      });
   }
}
public class Play {
   private JLabel[][] x;

   public Play(JLabel[][] x) { //This matrix is important (is an reference), is instanced in GameScene, this is an problem?
      this.x = x;
      //Define others variables
   }
}
   public class App extends JFrame {
       private JPanel rootPanel;
       private static App app;

       private App() {
          super("x");
          createApp();
       }

       public static App getInstance() {
          if (app == null) {
            app = new App();
          }

          return app;
       }

       private void createApp() {
         //Define JFrame, rootPanel, buttons, etc ...
       }

       public void runScene(JPanel scene) {
          rootPanel.removeAll();

          rootPanel.add(scene);
          rootPanel.revalidate();
          rootPanel.repaint();
       }

       public static void main(String[] args) { //Main
          getInstance().runScene(new MenuScene());
       }
    }
    public class GameScene extends JPanel {

    private Play p;
    private Timer t;
    private Event e; //Define controls (keyboard)
    private JLabel[][] mat;

    public GameScene() {
       //Define JPanel, Matrix, Play, Timer and Event
       ...
       buttonBackMenu.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent x) {
             This method is useful to create another scene for example from another instance other than this (GameScene)
             changeScene(new MenuScene());
         }
       });
    }

    public void changeScene(JPanel scene) {
        e.removeKeyDispatcher(); //You must create a method that allows you to move the event key dispatcher
        t.stopAllTimers(); //You must create a method to stop all timers, or any object that is active.
        t = null;
        e = null;
        p = null;
        //If you have more active objects and work with other instances of other classes they should be "broken" or "stopped" and then match their instance to null
        App.getInstance().runScene(scene);
    }

    //Optional...
    public JLabel[][] getMat() {
       return mat;
    }
 }
gamesence.java

public class App extends JFrame {
   private JPanel rootPanel;

   public App() {
      //Define frame
      ...
      runScene(new MenuScene(this));
   }

   public void runScene(JPanel scene) {
      destroyScene();

      rootPanel.setBackground(scene.getBackground());
      rootPanel.add(scene);
      rootPane.validate();
      rootPanel.repaint();
   }

   private void destroyScene() {
      rootPanel.removeAll();
      rootPanel.revalidate();
      rootPanel.repaint();
   }


   public static void main(String[] args) { //Main
      new App();
   }
}
public class MenuScene extends JPanel {
   private App app;

   public MenuScene(App app) {
      this.app = app;
      //Define JPanel
      ...
      buttonStart.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            app.runScene(new GameScene(app));
        }
      });
   }
}
public class GameScene extends JPanel {
   private App;
   private Play;
   private Timer;
   private Event; //Define controls (keyboard)

   public GameScene(App app) {
      this.app = app;
      //Define JPanel, Play, Timer and Event
      ...
      buttonBackMenu.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            app.runScene(new MenuScene(app));
        }
      });
   }
}
public class Play {
   private JLabel[][] x;

   public Play(JLabel[][] x) { //This matrix is important (is an reference), is instanced in GameScene, this is an problem?
      this.x = x;
      //Define others variables
   }
}
   public class App extends JFrame {
       private JPanel rootPanel;
       private static App app;

       private App() {
          super("x");
          createApp();
       }

       public static App getInstance() {
          if (app == null) {
            app = new App();
          }

          return app;
       }

       private void createApp() {
         //Define JFrame, rootPanel, buttons, etc ...
       }

       public void runScene(JPanel scene) {
          rootPanel.removeAll();

          rootPanel.add(scene);
          rootPanel.revalidate();
          rootPanel.repaint();
       }

       public static void main(String[] args) { //Main
          getInstance().runScene(new MenuScene());
       }
    }
    public class GameScene extends JPanel {

    private Play p;
    private Timer t;
    private Event e; //Define controls (keyboard)
    private JLabel[][] mat;

    public GameScene() {
       //Define JPanel, Matrix, Play, Timer and Event
       ...
       buttonBackMenu.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent x) {
             This method is useful to create another scene for example from another instance other than this (GameScene)
             changeScene(new MenuScene());
         }
       });
    }

    public void changeScene(JPanel scene) {
        e.removeKeyDispatcher(); //You must create a method that allows you to move the event key dispatcher
        t.stopAllTimers(); //You must create a method to stop all timers, or any object that is active.
        t = null;
        e = null;
        p = null;
        //If you have more active objects and work with other instances of other classes they should be "broken" or "stopped" and then match their instance to null
        App.getInstance().runScene(scene);
    }

    //Optional...
    public JLabel[][] getMat() {
       return mat;
    }
 }
Play.java

public class App extends JFrame {
   private JPanel rootPanel;

   public App() {
      //Define frame
      ...
      runScene(new MenuScene(this));
   }

   public void runScene(JPanel scene) {
      destroyScene();

      rootPanel.setBackground(scene.getBackground());
      rootPanel.add(scene);
      rootPane.validate();
      rootPanel.repaint();
   }

   private void destroyScene() {
      rootPanel.removeAll();
      rootPanel.revalidate();
      rootPanel.repaint();
   }


   public static void main(String[] args) { //Main
      new App();
   }
}
public class MenuScene extends JPanel {
   private App app;

   public MenuScene(App app) {
      this.app = app;
      //Define JPanel
      ...
      buttonStart.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            app.runScene(new GameScene(app));
        }
      });
   }
}
public class GameScene extends JPanel {
   private App;
   private Play;
   private Timer;
   private Event; //Define controls (keyboard)

   public GameScene(App app) {
      this.app = app;
      //Define JPanel, Play, Timer and Event
      ...
      buttonBackMenu.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            app.runScene(new MenuScene(app));
        }
      });
   }
}
public class Play {
   private JLabel[][] x;

   public Play(JLabel[][] x) { //This matrix is important (is an reference), is instanced in GameScene, this is an problem?
      this.x = x;
      //Define others variables
   }
}
   public class App extends JFrame {
       private JPanel rootPanel;
       private static App app;

       private App() {
          super("x");
          createApp();
       }

       public static App getInstance() {
          if (app == null) {
            app = new App();
          }

          return app;
       }

       private void createApp() {
         //Define JFrame, rootPanel, buttons, etc ...
       }

       public void runScene(JPanel scene) {
          rootPanel.removeAll();

          rootPanel.add(scene);
          rootPanel.revalidate();
          rootPanel.repaint();
       }

       public static void main(String[] args) { //Main
          getInstance().runScene(new MenuScene());
       }
    }
    public class GameScene extends JPanel {

    private Play p;
    private Timer t;
    private Event e; //Define controls (keyboard)
    private JLabel[][] mat;

    public GameScene() {
       //Define JPanel, Matrix, Play, Timer and Event
       ...
       buttonBackMenu.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent x) {
             This method is useful to create another scene for example from another instance other than this (GameScene)
             changeScene(new MenuScene());
         }
       });
    }

    public void changeScene(JPanel scene) {
        e.removeKeyDispatcher(); //You must create a method that allows you to move the event key dispatcher
        t.stopAllTimers(); //You must create a method to stop all timers, or any object that is active.
        t = null;
        e = null;
        p = null;
        //If you have more active objects and work with other instances of other classes they should be "broken" or "stopped" and then match their instance to null
        App.getInstance().runScene(scene);
    }

    //Optional...
    public JLabel[][] getMat() {
       return mat;
    }
 }

非常感谢您的帮助。

我找到了一个有点奇怪的解决方案,但我不知道它是否是最好的:

最好的方法是,由于GC不选择活动计时器,因此最好停止它们,并将其他对象匹配为null。使用Singleton模式,我有一个帧的单个实例,该实例将用于希望运行另一个场景的任何类(场景),这里是一个实现:

App.java

public class App extends JFrame {
   private JPanel rootPanel;

   public App() {
      //Define frame
      ...
      runScene(new MenuScene(this));
   }

   public void runScene(JPanel scene) {
      destroyScene();

      rootPanel.setBackground(scene.getBackground());
      rootPanel.add(scene);
      rootPane.validate();
      rootPanel.repaint();
   }

   private void destroyScene() {
      rootPanel.removeAll();
      rootPanel.revalidate();
      rootPanel.repaint();
   }


   public static void main(String[] args) { //Main
      new App();
   }
}
public class MenuScene extends JPanel {
   private App app;

   public MenuScene(App app) {
      this.app = app;
      //Define JPanel
      ...
      buttonStart.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            app.runScene(new GameScene(app));
        }
      });
   }
}
public class GameScene extends JPanel {
   private App;
   private Play;
   private Timer;
   private Event; //Define controls (keyboard)

   public GameScene(App app) {
      this.app = app;
      //Define JPanel, Play, Timer and Event
      ...
      buttonBackMenu.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            app.runScene(new MenuScene(app));
        }
      });
   }
}
public class Play {
   private JLabel[][] x;

   public Play(JLabel[][] x) { //This matrix is important (is an reference), is instanced in GameScene, this is an problem?
      this.x = x;
      //Define others variables
   }
}
   public class App extends JFrame {
       private JPanel rootPanel;
       private static App app;

       private App() {
          super("x");
          createApp();
       }

       public static App getInstance() {
          if (app == null) {
            app = new App();
          }

          return app;
       }

       private void createApp() {
         //Define JFrame, rootPanel, buttons, etc ...
       }

       public void runScene(JPanel scene) {
          rootPanel.removeAll();

          rootPanel.add(scene);
          rootPanel.revalidate();
          rootPanel.repaint();
       }

       public static void main(String[] args) { //Main
          getInstance().runScene(new MenuScene());
       }
    }
    public class GameScene extends JPanel {

    private Play p;
    private Timer t;
    private Event e; //Define controls (keyboard)
    private JLabel[][] mat;

    public GameScene() {
       //Define JPanel, Matrix, Play, Timer and Event
       ...
       buttonBackMenu.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent x) {
             This method is useful to create another scene for example from another instance other than this (GameScene)
             changeScene(new MenuScene());
         }
       });
    }

    public void changeScene(JPanel scene) {
        e.removeKeyDispatcher(); //You must create a method that allows you to move the event key dispatcher
        t.stopAllTimers(); //You must create a method to stop all timers, or any object that is active.
        t = null;
        e = null;
        p = null;
        //If you have more active objects and work with other instances of other classes they should be "broken" or "stopped" and then match their instance to null
        App.getInstance().runScene(scene);
    }

    //Optional...
    public JLabel[][] getMat() {
       return mat;
    }
 }
gamesence.java

public class App extends JFrame {
   private JPanel rootPanel;

   public App() {
      //Define frame
      ...
      runScene(new MenuScene(this));
   }

   public void runScene(JPanel scene) {
      destroyScene();

      rootPanel.setBackground(scene.getBackground());
      rootPanel.add(scene);
      rootPane.validate();
      rootPanel.repaint();
   }

   private void destroyScene() {
      rootPanel.removeAll();
      rootPanel.revalidate();
      rootPanel.repaint();
   }


   public static void main(String[] args) { //Main
      new App();
   }
}
public class MenuScene extends JPanel {
   private App app;

   public MenuScene(App app) {
      this.app = app;
      //Define JPanel
      ...
      buttonStart.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            app.runScene(new GameScene(app));
        }
      });
   }
}
public class GameScene extends JPanel {
   private App;
   private Play;
   private Timer;
   private Event; //Define controls (keyboard)

   public GameScene(App app) {
      this.app = app;
      //Define JPanel, Play, Timer and Event
      ...
      buttonBackMenu.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            app.runScene(new MenuScene(app));
        }
      });
   }
}
public class Play {
   private JLabel[][] x;

   public Play(JLabel[][] x) { //This matrix is important (is an reference), is instanced in GameScene, this is an problem?
      this.x = x;
      //Define others variables
   }
}
   public class App extends JFrame {
       private JPanel rootPanel;
       private static App app;

       private App() {
          super("x");
          createApp();
       }

       public static App getInstance() {
          if (app == null) {
            app = new App();
          }

          return app;
       }

       private void createApp() {
         //Define JFrame, rootPanel, buttons, etc ...
       }

       public void runScene(JPanel scene) {
          rootPanel.removeAll();

          rootPanel.add(scene);
          rootPanel.revalidate();
          rootPanel.repaint();
       }

       public static void main(String[] args) { //Main
          getInstance().runScene(new MenuScene());
       }
    }
    public class GameScene extends JPanel {

    private Play p;
    private Timer t;
    private Event e; //Define controls (keyboard)
    private JLabel[][] mat;

    public GameScene() {
       //Define JPanel, Matrix, Play, Timer and Event
       ...
       buttonBackMenu.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent x) {
             This method is useful to create another scene for example from another instance other than this (GameScene)
             changeScene(new MenuScene());
         }
       });
    }

    public void changeScene(JPanel scene) {
        e.removeKeyDispatcher(); //You must create a method that allows you to move the event key dispatcher
        t.stopAllTimers(); //You must create a method to stop all timers, or any object that is active.
        t = null;
        e = null;
        p = null;
        //If you have more active objects and work with other instances of other classes they should be "broken" or "stopped" and then match their instance to null
        App.getInstance().runScene(scene);
    }

    //Optional...
    public JLabel[][] getMat() {
       return mat;
    }
 }
Play.java、Event.java、Timer.java(X)


当你从游戏中按back键时,你应该拆除/销毁游戏控件,特别是计时器,你还应该取消对app变量的引用,以防止任何循环引用1)“我给你一个最重要类的概述:”为了更快地获得更好的帮助,请发布或。2)
rootPanel.removeAll();rootPanel.revalidate();rootPanel.repaint()使用,如中所示。