且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用按钮添加新的JFrame?

更新时间:2023-12-03 12:40:46

您似乎对容器管理的工作方式有疑问.停下来,退一步,然后重新考虑您的方法.

You seem to have issues with how container management works. Stop, take a step back for a second and re-think your approach.

基本上,您有一个菜单"和一个游戏"面板.这应该是两个单独的面板/类.

You basically have a "menu" and a "game" panel. This should be two separate panels/class.

然后应将这些添加到集线器"面板,该面板管理何时以及如何显示它们.

These should then be added to a "hub" panel, which manages when and how they are displayed.

这是主",集线器"面板.它负责显示菜单和游戏面板.它还负责确定这种情况的如何发生",在本示例中,我仅使用了CardLayout

This is the "main", "hub" panel. It is responsible for displaying both the menu and the game panels. It's also responsible for deciding "how" this happens, in this example, I've simply used a CardLayout

public class MainPane extends JPanel {

    public MainPane() {
        setLayout(new CardLayout());

        MenuPane menu = new MenuPane();
        menu.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (getLayout() instanceof CardLayout) {
                    CardLayout layout = (CardLayout) getLayout();
                    layout.show(MainPane.this, "game");
                }
            }
        });
        GamePane game = new GamePane();

        add(menu, "menu");
        add(game, "game");

        ((CardLayout) getLayout()).show(this, "menu");
    }

}

MenuPane

菜单"非常简单.它仅显示可用选项,并提供一种在选择选项时通知感兴趣的参与者的方法

MenuPane

The "menu" is pretty simple. It simply displays the available options and provides a means for interested parties to be notified when an option is selected

public class MenuPane extends JPanel {

    private JButton btn;

    public MenuPane() {
        setLayout(new GridBagLayout());
        setBackground(Color.BLUE);
        btn = new JButton("Start");
        add(btn);
    }

    public void addActionListener(ActionListener listener) {
        btn.addActionListener(listener);
    }

    public void removeActionListener(ActionListener listener) {
        btn.removeActionListener(listener);
    }

}

我对此不做过多介绍,但是您应该看看如何使用按钮,复选框和单选按钮如何编写动作监听器了解更多详情

I'm not going into a lot about this, but you should have a look at How to Use Buttons, Check Boxes, and Radio Buttons and How to Write an Action Listener for more details

我很懒,直接将ActionListener附加到按钮上.相反,您应该分别管理按钮侦听器和面板的侦听器,这样可以防止暴露按钮,并使您可以更好地控制执行特定操作时生成的内容.

I'm been lazy, attaching the ActionListeners directly to the buttons. Instead, you should manage the button listeners and the panel's listeners separately, this will prevent exposing the buttons and allow you better control over what to generate when a specific operation is executed.

最后是游戏"面板.正如我前一天所说的,您应该使用自定义绘画路线如何使用键绑定.他们将共同解决许多其他我们通常不想再被问到的问题

And finally, the "game" panel. As I've been saying for the last day, you should make use a custom painting route and How to Use Key Bindings. Together, they will solve a swagger of other issues we'd generally like not to have to be asked about, again

public interface Movable {

    public void changeLocation(int xDelta, int yDelta);
}

public class GamePane extends JPanel implements Movable {

    private Rectangle player;

    public GamePane() {
        String text = "X";
        FontMetrics fm = getFontMetrics(getFont());
        int width = fm.stringWidth(text);
        int height = fm.getHeight();

        player = new Rectangle(0, 0, width, height);

        setupKeyBindings();
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }

    protected void setupKeyBindings() {
        InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
        ActionMap am = getActionMap();

        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "up");
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), "down");
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), "left");
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "right");

        int xDelta = player.width;
        int yDelta = player.height;

        am.put("up", new MoveAction(this, 0, -yDelta));
        am.put("down", new MoveAction(this, 0, yDelta));
        am.put("left", new MoveAction(this, -xDelta, 0));
        am.put("right", new MoveAction(this, xDelta, 0));
    }

    @Override
    public void changeLocation(int xDelta, int yDelta) {
        int xPos = player.x + xDelta;
        int yPos = player.y + yDelta;
        if (xPos + player.width > getWidth()) {
            xPos = getWidth() - player.width;
        } else if (xPos < 0) {
            xPos = 0;
        }
        if (yPos + player.height > getHeight()) {
            yPos = getHeight() - player.height;
        } else if (xPos < 0) {
            yPos = 0;
        }
        player.setLocation(xPos, yPos);
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setColor(Color.RED);
        g2d.draw(player);
        FontMetrics fm = g2d.getFontMetrics();
        g2d.drawString("X", player.x, player.y + fm.getAscent());
        g2d.dispose();
    }

}

public class MoveAction extends AbstractAction {

    private Movable movable;
    private int xDelta;
    private int yDelta;

    public MoveAction(Movable movable, int xDelta, int yDelta) {
        this.movable = movable;
        this.xDelta = xDelta;
        this.yDelta = yDelta;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        movable.changeLocation(xDelta, yDelta);
    }

}

可运行示例...

将它们放在一起...

Runnable Example...

Putting it all together...

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Game {

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

    public Game() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new MainPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class MainPane extends JPanel {

        public MainPane() {
            setLayout(new CardLayout());

            MenuPane menu = new MenuPane();
            menu.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (getLayout() instanceof CardLayout) {
                        CardLayout layout = (CardLayout) getLayout();
                        layout.show(MainPane.this, "game");
                    }
                }
            });
            GamePane game = new GamePane();

            add(menu, "menu");
            add(game, "game");

            ((CardLayout) getLayout()).show(this, "menu");
        }

    }

    public class MenuPane extends JPanel {

        private JButton btn;

        public MenuPane() {
            setLayout(new GridBagLayout());
            setBackground(Color.BLUE);
            btn = new JButton("Start");
            add(btn);
        }

        public void addActionListener(ActionListener listener) {
            btn.addActionListener(listener);
        }

        public void removeActionListener(ActionListener listener) {
            btn.removeActionListener(listener);
        }

    }

    public interface Movable {

        public void changeLocation(int xDelta, int yDelta);
    }

    public class GamePane extends JPanel implements Movable {

        private Rectangle player;

        public GamePane() {
            String text = "X";
            FontMetrics fm = getFontMetrics(getFont());
            int width = fm.stringWidth(text);
            int height = fm.getHeight();

            player = new Rectangle(0, 0, width, height);

            setupKeyBindings();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void setupKeyBindings() {
            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap am = getActionMap();

            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "up");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), "down");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), "left");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "right");

            int xDelta = player.width;
            int yDelta = player.height;

            am.put("up", new MoveAction(this, 0, -yDelta));
            am.put("down", new MoveAction(this, 0, yDelta));
            am.put("left", new MoveAction(this, -xDelta, 0));
            am.put("right", new MoveAction(this, xDelta, 0));
        }

        @Override
        public void changeLocation(int xDelta, int yDelta) {
            int xPos = player.x + xDelta;
            int yPos = player.y + yDelta;
            if (xPos + player.width > getWidth()) {
                xPos = getWidth() - player.width;
            } else if (xPos < 0) {
                xPos = 0;
            }
            if (yPos + player.height > getHeight()) {
                yPos = getHeight() - player.height;
            } else if (xPos < 0) {
                yPos = 0;
            }
            player.setLocation(xPos, yPos);
            repaint();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.RED);
            g2d.draw(player);
            FontMetrics fm = g2d.getFontMetrics();
            g2d.drawString("X", player.x, player.y + fm.getAscent());
            g2d.dispose();
        }

    }

    public class MoveAction extends AbstractAction {

        private Movable movable;
        private int xDelta;
        private int yDelta;

        public MoveAction(Movable movable, int xDelta, int yDelta) {
            this.movable = movable;
            this.xDelta = xDelta;
            this.yDelta = yDelta;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            movable.changeLocation(xDelta, yDelta);
        }

    }

}

请记住,您的目标之一应该是关于责任分工",创建可以很好地完成工作的类/组件.这样,您就可以将它们用作设计更复杂解决方案的基础

Remember, one of your goals should be about "separation of responsibility", creating classes/components which do there job and do it well. This way you can use them as building blocks to devise much more complex solutions