如何添加带按钮的新JFrame?

时间:2018-05-26 04:48:39

标签: java swing graphics jframe

每当我创建一个新的JFrame屏幕时,由于某种原因,游戏不会在我的电脑上运行,我不知道为什么。我试过修复这个问题,但我认为它与按钮或屏幕的位置有关。 startStage是我需要帮助的。如果我遗失了什么,请告诉我。

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashSet;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

/**
 * This class demonstrates basic animation using a timer, an action listener,
 * and a key listener
 * 
 * 
 *
 */
public class GameWindow extends JPanel implements ActionListener, KeyListener {

 private static final long serialVersionUID = 1L;
 JLabel player = new JLabel();
 int playerSpeed = 1;
 int FPS = 30;
 // The keys set holds the keys being pressed
 private final Set<Integer> keys = new HashSet<>();

public static void main(String[] args) {
 // Open the GUI window
 SwingUtilities.invokeLater(new Runnable() {
  @Override
  public void run() {
  // Create a new object and
  // run its go() method
  new GameWindow().go();
  }
 });
}

public GameWindow() {
 // Run the parent class constructor
 super();
 // Allow the panel to get focus
 setFocusable(true);
 // Don't let keys change the focus
 setFocusTraversalKeysEnabled(false);

//Make a new screen with a button and put it in the window
JPanel startStage = new JPanel(); // Create a new JPanel and add it to the card layout
startStage.setSize(getWidth(), getHeight()); // make the new JPanel fit the window
startStage.setBackground(Color.BLUE); // set the JPanel background to blue
startStage.setVisible(true); // show the JPanel
JButton playButton = new JButton("Play"); // Add a button to the panel
playButton.addMouseListener(new MouseAdapter() { // Set the button to switch to the game stage
 @Override
 public void mouseClicked(MouseEvent arg0) {
  ((CardLayout) getContentPane().getLayout()).show(
   getContentPane(), "game");
 }
});
startStage.add(playButton); // add the button to the stage
add(startStage, "start"); // add the stage to the window

}

protected void go() {
 // Setup the window
 JFrame jf = new JFrame();
 // Add this panel to the window
 jf.setContentPane(this);
 // Set the window properties
 jf.setTitle("Animation Demo");
 jf.setSize(300, 200);
 jf.setLocationRelativeTo(null);
 jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 jf.setVisible(true);

 // Setup the movable box
 player.setBounds(10, 10, 10, 10);
 player.setVisible(true);
 player.setBackground(Color.BLUE);
 // Opaque makes the background visible
 player.setOpaque(true);

 // Setup the key listener
 addKeyListener(this);
 // Null layout allows moving objects!!!
 setLayout(null);
 add(player);

 // Set the timer
 Timer tm = new Timer(1000 / FPS, this);
 tm.start();
}

@Override
public void actionPerformed(ActionEvent arg0) {
 // Move up if W is pressed
 if (keys.contains(KeyEvent.VK_W)) {
  player.setLocation(player.getX(), player.getY() - playerSpeed);
 }
 // Move right if D is pressed
 if (keys.contains(KeyEvent.VK_D)) {
  player.setLocation(player.getX() + playerSpeed, player.getY());
 }
 // Move down if S is pressed
 if (keys.contains(KeyEvent.VK_S)) {
  player.setLocation(player.getX(), player.getY() + playerSpeed);
 }
 // Move left if A is pressed
 if (keys.contains(KeyEvent.VK_A)) {
  player.setLocation(player.getX() - playerSpeed, player.getY());
 }
}

@Override
public void keyPressed(KeyEvent e) {
 // Add the key to the list
 // of pressed keys
 if (!keys.contains(e.getKeyCode())) {
  keys.add(e.getKeyCode());
 }
}

@Override
public void keyReleased(KeyEvent e) {
 // Remove the key from the
 // list of pressed keys
 keys.remove((Integer) e.getKeyCode());
}

@Override
public void keyTyped(KeyEvent e) {
}

}

1 个答案:

答案 0 :(得分:1)

您似乎对容器管理的工作方式存在问题。停下来,退后一步,重新思考你的方法。

你基本上有一个&#34;菜单&#34;和#34;游戏&#34;面板。这应该是两个单独的小组/类。

然后将这些添加到&#34; hub&#34;面板,管理它们的显示时间和方式。

MainPane

这是&#34;主要&#34;,&#34; hub&#34;面板。它负责显示菜单和游戏面板。它还负责决定&#34;如何&#34;发生这种情况,在这个例子中,我只使用了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

&#34;菜单&#34;很简单。它只显示可用选项,并为选择选项时通知相关方提供方法

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);
    }

}

我不会对此有太多了解,但您应该查看How to Use Buttons, Check Boxes, and Radio ButtonsHow to Write an Action Listener了解更多详情

声明...

我很懒,将ActionListener直接贴在按钮上。相反,您应该分别管理按钮侦听器和面板的侦听器,这将防止暴露按钮并允许您更好地控制执行特定操作时生成的内容。

GamePane

最后,#34;游戏&#34;面板。正如我在最后一天所说的那样,你应该使用custom painting routeHow to Use Key Bindings。他们将共同解决我们通常不想再被问到的其他问题,

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);
    }

}

可运行的示例...

全部放在一起......

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);
        }

    }

}

请记住,您的目标之一应该是&#34;责任分离&#34;,创建完成工作并做得好的类/组件。通过这种方式,您可以将它们用作构建块来设计更复杂的解决方案