How can I switch between jpanels?

后端 未结 3 913
独厮守ぢ
独厮守ぢ 2020-12-11 21:28

I\'m still very new to java programming, so please help me to correct any mistakes I might have overlooked or give tips on how to improve this program.

Okay, so a lo

相关标签:
3条回答
  • 2020-12-11 21:49

    The best way to approach this is using a CardLayout.

    enter image description here

    enter image description here

    Notes

    • A button with an ActionListener is far better than a MouseListener over a rectangle.
      • The button will show focus when the mouse is pointed at it, or the component is tabbed to via the keyboard.
      • The button is keyboard accessible.
      • The button has facility to support multiple icons built in (e.g. for 'initial look', focused, pressed etc.)
    • White space in the GUI is provided around the menu panel and game by adding an EmptyBorder
    • The button is made larger by setting a margin.
    • Adjust margins, borders and preferred size according to need. These sizes were set by me so as not to make the screenshots too large.
    • See more tips in the code comments.

    Code

    Here is the MCTaRE (Minimal Complete Tested and Readable Example) that produced the above screenshots.

    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.*;
    import javax.swing.border.EmptyBorder;
    
    public class PipesGame {
    
        public static void main(String[] args) {
            Runnable r = new Runnable() {
                @Override
                public void run() {
                    // the GUI as seen by the user (without frame)
                    final CardLayout cl = new CardLayout();
                    final JPanel gui = new JPanel(cl);
                    // remove if no border is needed
                    gui.setBorder(new EmptyBorder(10,10,10,10));
    
                    JPanel menu = new JPanel(new GridBagLayout());
                    JButton playGame = new JButton("Play!");
                    ActionListener playGameListener = new ActionListener() {
    
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            cl.show(gui, "game");
                        }
                    };
                    playGame.addActionListener(playGameListener);
                    Insets margin = new Insets(20, 50, 20, 50);
                    playGame.setMargin(margin);
                    menu.add(playGame);
                    gui.add(menu);
                    cl.addLayoutComponent(menu, "menu");
    
                    JPanel pipes = new Pipes();
                    gui.add(pipes);
                    cl.addLayoutComponent(pipes, "game");
    
                    JFrame f = new JFrame("Pipes Game");
                    f.add(gui);
                    // Ensures JVM closes after frame(s) closed and
                    // all non-daemon threads are finished
                    f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                    // See https://stackoverflow.com/a/7143398/418556 for demo.
                    f.setLocationByPlatform(true);
    
                    // ensures the frame is the minimum size it needs to be
                    // in order display the components within it
                    f.pack();
                    // should be done last, to avoid flickering, moving,
                    // resizing artifacts.
                    f.setVisible(true);
                }
            };
            // Swing GUIs should be created and updated on the EDT
            // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
            SwingUtilities.invokeLater(r);
        }
    }
    
    class Pipes extends JPanel {
    
        Pipes() {
            setBackground(Color.BLACK);
            setForeground(Color.WHITE);
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawString("Pipes game appears here..", 170, 80);
        }
    
        @Override 
        public Dimension getPreferredSize() {
            // adjust to need
            return new Dimension(500,150);
        }
    }
    
    0 讨论(0)
  • 2020-12-11 21:52

    This works with a mouse click on the menu. You can change it later, to a click on some button or whatever you want.

    I added a MouseListener to the Game class. When the user presses the mouse on the menu JPanel, it adds the Pipes JPanel to JFrame and calls the pack method.

    Game.java:

    import java.awt.Point;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.geom.Rectangle2D;
    
    import javax.swing.JFrame;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    
    public class Game {
    
        GameMenu menu = new GameMenu();
        Pipes game;
        boolean start = false;
        JFrame f;
        Rectangle2D menuRect = new Rectangle2D.Double(20, 20, 60, 40);
    
        public Game() {
            f = new JFrame();
    
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(menu);
            f.setTitle("Pipe Game");
            f.setResizable(false);
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
    
    
    
            menu.addMouseListener(new MouseAdapter() {
    
                @Override
                public void mousePressed(MouseEvent e) {
    
                    Point click = new Point(e.getX(), e.getY());
                    System.out.println("Clicked on the Panel");
    
                    if(menuRect.contains(click))
                    {
                        System.out.println("Clicked inside the Rectangle.");
    
                        start = true; 
                        menu.setVisible(false);
                        game = new Pipes();
                        f.add(game);
                        f.pack();
    
                        Timer timer = new Timer(10, new ActionListener() {  //pipe speed
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                game.move();
                            }
                        });
                        timer.start();
    
                        Timer refresh = new Timer(30, new ActionListener() {    //refresh rate
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                game.repaint();
                            }
                        });
                        refresh.start();   
                    }
                }
    
                @Override
                public void mouseReleased(MouseEvent e) {
                }
            });
    
        }
    
        public static void main(String args[]) {
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    new Game();
                }
            });
        }
    }
    
    0 讨论(0)
  • 2020-12-11 21:55

    "Is there a way for me to add my GameMenu jpanel to my jframe, and then replace it with the Pipes jpanel?"

    As other have suggested, for this you want a CardLayout. It is very simple to you. Personally, I always wrap my CardLayout in a JPanel rather than the JFrame, just force of habit.

    What you want to do is have a mainPanel that will have the CardLayout

    CardLayout card = new CardLayout();
    JPanel mainPanel = new JPanel();
    

    Then you want to add your panels to the mainPanel. What the CardLyaout does is layer the panels, making just one visible at a time. The first one you add, will the in the foreground. Also when you add the panel, you'll also want to issue it a key it can be called from. The key, can be any String you like.

    mainPanel.add(gameMenu, "menu");
    mainPnael.add(pipes, "pipe");
    

    Now gameMenu is the only panel shown. To show pipes, all you do is use this method

    • public void show(Container parent, String name) - Flips to the parent that was added to this layout with the specified name, using addLayoutComponent. If no such component exists, then nothing happens.

    So you'd use, card.show(mainPanel, "pipes");

    Whatever even you want to trigger the showing of pipes, just add that line in that event handler. You could add a button or something to the GameMenu that will allow movement to the Pipes panel.

    0 讨论(0)
提交回复
热议问题