如何使用按钮添加新的JFrame? [英] How to add a new JFrame with buttons?
问题描述
每当我创建一个新的JFrame
屏幕时,由于某种原因游戏将无法在计算机上运行,我也不知道为什么.我曾尝试解决此问题,但我认为这与按钮或屏幕的位置有关. startStage
是我需要帮助的.如果我想念什么,可以告诉我.
Whenever I create a new JFrame
screen the game won't run on my computer for some reason and I don't know why. I have tried fixing this issue but I think it has something to do with the buttons or the placement of the screen. The startStage
is what I need help on. If I'm missing something can you please tell me.
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) {
}
}
推荐答案
您似乎对容器管理的工作方式有疑问.停下来,退一步,然后重新考虑您的方法.
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 ActionListener
s 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
这篇关于如何使用按钮添加新的JFrame?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!