如何修复 JPanel 循环?

How to fix JPanel loop?

我已经完成了简单的形状游戏。代码有 3 个 JPanel,其中包含开始、游戏和游戏结束。在代码中,一切都是完美的,但游戏结束时我必须包括计算鼠标点击的游戏得分 score.I 不能包括最后一个面板 JPanel 中的 score.That 得分页面。并且我包含了 JButton,例如 {try again} 和 {exit}。当我按下重试按钮时,我无法完美地看到我的第一个 Jpanel,它包含开始按钮。我该如何解决? 这是沉重的代码,我希望它不是乱七八糟的

    public class myshapestry  implements ActionListener {

        JFrame frame= new JFrame();
        MyPanel panel=new MyPanel();
        Container l ;
        private int ballXSpeed=150;
        private  int ballSpeed=90;
        private  int ballX=150;
        private  int ballY=200;
        Color c=Color.BLACK;
        JLabel statusbar = new JLabel("This game is developed by Asuskobay");
        Startthegame panelstart= new Startthegame();//this is start JPanel
        chooselevel panellevel= new chooselevel();//this is difficulties JPanel
        thegameover gameover=new thegameover();//End of page
       private int mouseclicks;//mouseclicks score
       private int mouse;

         public myshapestry() {

             frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
             frame.pack();
             frame.setLocationRelativeTo(null);
             frame.add(panel);
             frame.add(panellevel);
             frame.add(gameover);
             frame.add(panelstart);
            frame.add(statusbar, BorderLayout.SOUTH);
            frame.setVisible(true);
             frame.setSize(getPreferredSize());
            frame.setTitle("Game of Shapes");
              HandlerClass handler=new HandlerClass();
                panel.addMouseListener(handler);
                panel.addMouseMotionListener(handler);
                Timer timer=new Timer(100,panel) ;
                timer.start();
            }

         public Dimension getPreferredSize() {
               return new  Dimension(900,730);
           }
         private  class HandlerClass implements MouseMotionListener, MouseListener {
               public void mouseClicked(MouseEvent e){

                 mouseclicks++;
                 statusbar.setText(String.format("MouseLoc ( %d, %d ) \t \t Mouse Click \t", e.getX(), e.getY()) + mouseclicks);
                 mouseclicks=mouse;
               }
              @Override
                public void mousePressed(MouseEvent event) {
                    if(event.getX() <= (ballX+90) && event.getX() >= (ballX)  && event.getY() <= (ballY+90) && event.getY() >= (ballY))
                       c=Color.RED;

                } }
          public  class MyPanel extends JPanel implements ActionListener {

               public void paintComponent(Graphics g){
                   super.paintComponent(g);
                   g.setColor(c);
                   g.fillOval(ballX, ballY, 90 , 90);
                  }
               public void actionPerformed(ActionEvent e) { //balls movement
                  ballX = ballX + ballXSpeed;
                  ballY = ballY + ballSpeed;
                  if(ballY>=730-185){

                     ballSpeed = -ballSpeed;
                  }

                  if(ballX>=900-180){
                      ballXSpeed = -ballXSpeed;
                  }

                  if(ballY<=0+60){
                      ballSpeed= -ballSpeed;

                  }

                  if (ballX<=0+60){
                      ballXSpeed= -ballXSpeed;
                  }

                  repaint();
                 if(c==Color.RED){
                     frame.remove(panel);
                     frame.add(gameover);
                     frame.validate();
                 }}}
           public class chooselevel extends JPanel implements ActionListener {
               private JButton easy;
               private JButton normal;
               private JButton hard;

               public chooselevel(){
                   setLayout(null);
                   easy=new JButton("Easy");
                   normal=new JButton("Normal");
                   hard=new JButton("Hard");

                   easy.setBounds(380,330,90,20);
                   normal.setBounds(380,370,90,20);
                   hard.setBounds(380,410,90,20);
                   add(hard);
                   add(easy);
                   add(normal);
                        hard.addActionListener(new ActionListener(){

                       public void actionPerformed(ActionEvent l){
                           String level=l.getActionCommand();
                           if(level.equals("Hard")){
                               ballXSpeed=190;
                               ballSpeed=184;
                               frame.remove(panellevel);
                               frame.add(panel);
                               frame.validate();
                           }} });  

                   normal.addActionListener(new ActionListener(){

                       public void actionPerformed(ActionEvent l){
                           String level=l.getActionCommand();
                           if(level.equals("Normal")){
                               ballXSpeed=157;
                               ballSpeed=123;
                               frame.remove(panellevel);
                               frame.add(panel);
                               frame.validate();

                           }}});

                   easy.addActionListener(new ActionListener(){

                       public void actionPerformed(ActionEvent l){
                           String level=l.getActionCommand();

                             if(level.equals("Easy")){
                               ballXSpeed=85;
                               ballSpeed=74;
                               frame.remove(panellevel);
                               frame.add(panel);
                               frame.validate();
                              }} });

               } 
              public Dimension getPreferredSize() {
                   return new Dimension(900,730);
               } }
           public class Startthegame extends JPanel implements ActionListener {
               private JButton Start;
                private JButton Exit;

                public Startthegame() {
                    setLayout(null);

                    Start = new JButton("Start");
                    Exit = new JButton("Exit");

                    Start.setBounds(380,330,70,20);
                    Exit.setBounds(380,370,70,20);
                    add(Start);
                    add(Exit);
                     Exit.addActionListener(new ActionListener() {

                     public  void  actionPerformed(ActionEvent i){
                       String action= i.getActionCommand();
                       if(action.equals("Exit")) {
                         System.exit(0);
                       }}
                 });
                    Start.addActionListener(new ActionListener() {

                         public  void  actionPerformed(ActionEvent i){
                           String action= i.getActionCommand();
                           if(action.equals("Start")) {
                               frame.remove(panelstart);
                               frame.add(panellevel);
                               frame.validate();
                               repaint();
                           } }});
}
    @Override
                public Dimension getPreferredSize() {
                    return new Dimension(900, 730);
                } }
           public class thegameover extends JPanel {
               private JLabel gameisover;
               private JLabel yourscore;
               private JButton tryagain;
               private JButton Exit;
               thegameover(){
                   setLayout(null);

                   gameisover= new JLabel("GAME OVER");
                   yourscore=new JLabel();

                  add(gameisover);
                  add(yourscore);
                   gameisover.setBounds(170,200,600,70);
                   yourscore.setBounds(380,380,120,70);

                  gameisover.setFont(new Font(null, Font.PLAIN, 90));
                  yourscore.setFont(new Font(null, Font.PLAIN, 20));
                  yourscore.setText ("Your Score " + mouseclicks);

                  tryagain=new JButton("Try Again");
                  Exit=new JButton("Exit");
                  add(tryagain);
                  add(Exit);

                  tryagain.setBounds(280,550,100,20);
                  Exit.setBounds(490,550,100,20);

                  tryagain.addActionListener(new ActionListener() {

                      public void actionPerformed(ActionEvent ac){
                          String tryit=ac.getActionCommand();
                                if(tryit.equals("Try Again")){
                                     frame.remove(gameover);
                                       frame.add(panelstart);
                                       frame.validate();
                                       repaint();
                                }
                            }
                  });
               }
               public Dimension getPreferredSize(){
                   return new Dimension(900,73);
               }}
            public static void main (String args[]){
               EventQueue.invokeLater(new Runnable() {
                   @Override
                   public void run() {

                       myshapestry tr=new myshapestry();
                   }
               });
             }  }

编辑后:

我创建了新的 Jpanel 来收集其中的所有 Jpanel,以便在 Frame 中添加状态栏,但我收到错误,出了点问题

public class myshapestry  implements ActionListener {
    collectionpanel collectpanel= new collectionpanel();

public myshapestry() {
        frame.add(collectpanel);
public class collectionpanel extends JPanel {



         collectionpanel(){
                cardlayout= new CardLayout();
                 this.setLayout(cardlayout);
                 this.add(panel, "game");
                this.add(panellevel,"level");
                 this.add(gameover, "over");
                 this.add(panelstart, "start");

                 cardlayout.show(collectpanel, "game");
             cardlayout.show(collectpanel, "level");
             cardlayout.show(collectpanel, "start");
             cardlayout.show(collectpanel, "over");     

         } }

错误;

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: wrong parent for CardLayout
    at java.awt.CardLayout.checkLayout(Unknown Source)
    at java.awt.CardLayout.show(Unknown Source)
    at example.myshapestry$collectionpanel.<init>(myshapestry.java:100)
    at example.myshapestry.<init>(myshapestry.java:58)
    at example.myshapestry.run(myshapestry.java:393)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access0(Unknown Source)
    at java.awt.EventQueue.run(Unknown Source)
    at java.awt.EventQueue.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

存在一连串的问题,所有问题共同作用导致混乱...

  1. 当游戏是 "over" 时,您永远不会停止 Timer,这意味着当您尝试显示 "game over" 屏幕或尝试重新启动时,"game panel" 仍在尝试更新屏幕...
  2. 您对屏幕的管理使情况更加复杂。您一开始就添加了所有屏幕,但稍后又 remove/add 它们,这只会造成混乱。

而是...

  1. 在使 "game screen" 可见之前,启动 Timer。当您检测到游戏为"over"时,在显示"over"屏幕之前,停止Timer
  2. 改用 CardLayout。有关详细信息,请参阅 How to Use CardLayout

例如...

创建一个 CardLayout 实例字段并将 Timer 也设为实例字段

public class MyShapes {//implements ActionListener {
    //...       
    private CardLayout cardLayout;
    private Timer timer = new Timer(100, panel);

CardLayout 应用于 frame 并命名每个视图...

public MyShapes() {
    //...       
    cardLayout = new CardLayout();
    frame.setLayout(cardLayout);

    frame.add(panel, "game");
    frame.add(panellevel, "level");
    frame.add(gameover, "over");
    frame.add(panelstart, "start");
    frame.add(statusbar, BorderLayout.SOUTH);

    cardLayout.show(frame.getContentPane(), "start");
    //...
}

当用户选择 "start" 时,使用 CardLayout

切换视图
Start.addActionListener(new ActionListener() {

    public void actionPerformed(ActionEvent i) {
        String action = i.getActionCommand();
        if (action.equals("Start")) {
            //frame.remove(panelstart);
            //frame.add(panellevel);
            //frame.validate();
            cardLayout.show(frame.getContentPane(), "level");
        }
    }
});

开始游戏时,启动Timer并使用CardLayout切换视图...

hard.addActionListener(new ActionListener() {

    public void actionPerformed(ActionEvent l) {
        String level = l.getActionCommand();
        if (level.equals("Hard")) {
            ballXSpeed = 190;
            ballSpeed = 184;
            //frame.remove(panellevel);
            //frame.add(panel);
            //frame.validate();
            timer.start();
            cardLayout.show(frame.getContentPane(), "game");
        }
    }
});

当您检测到 "game over" 条件时,停止 Timer 并使用 CardLayout 切换视图...

if (c == Color.RED) {
    //frame.remove(panel);
    //frame.add(gameover);
    //frame.validate();
    timer.stop();
    cardLayout.show(frame.getContentPane(), "over");
}

现在,关于得分问题...

当您创建 thegameover 面板时,您使用 yourscore.setText("Your Score " + mouseclicks);,但是当您创建视图时 mouseclicks0,您需要以某种方式更新此值。 ...

thegameover 添加方法 class,调用类似于 setScore 的方法并相应地更新标签...

public void setScore(int score) {
    yourscore.setText("Your Score " + score);
}

当您检测到游戏结束时,更新比分...

timer.stop();
gameover.setScore(mouseclicks);
cardLayout.show(frame.getContentPane(), "over");

您可能希望通读 Code Conventions for the Java TM Programming Language,这将使人们更容易阅读您的代码,您也可以更轻松地阅读其他人

阅读 Laying Out Components Within a Container

也是值得的