Java 在JFrame中看不到矩形播放器类
我是java新手,正在尝试创建一个基本的游戏,现在正在尝试编写player类。但是,当我运行游戏时,只有JFRame出现。这些是我的thress类,它们没有显示错误Java 在JFrame中看不到矩形播放器类,java,swing,Java,Swing,我是java新手,正在尝试创建一个基本的游戏,现在正在尝试编写player类。但是,当我运行游戏时,只有JFRame出现。这些是我的thress类,它们没有显示错误 import java.awt.Color; import javax.swing.JFrame; public class Game extends JFrame { public final static int WIDTH = 700, HEIGHT = 450; public GamePanel pa
import java.awt.Color;
import javax.swing.JFrame;
public class Game extends JFrame {
public
final static int WIDTH = 700, HEIGHT = 450;
public
GamePanel panel;
public Game() {
setSize(WIDTH, HEIGHT);
setTitle("Game");
setBackground(Color.WHITE);
setResizable(false);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new GamePanel(this);
add(panel);
}
public GamePanel getPanel() {
return panel;
}
public static void main(String[] args) {
new Game();
}
}
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements ActionListener, KeyListener {
public
Game game;
public
Player player;
public GamePanel(Game game) {
setBackground(Color.GREEN);
this.game = game;
player = new Player(game, KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, game.getWidth() - 36);
addKeyListener(this);
setFocusable(true);
}
public
void update() {
player.update();
}
public void actionPerformed(ActionEvent e) {
update();
repaint();
}
public Player getPlayer(int playerNo) {
return player;
}
public void keyPressed(KeyEvent e) {
player.pressed(e.getKeyCode());
}
public void keyReleased(KeyEvent e) {
player.released(e.getKeyCode());
}
public void keyTyped(KeyEvent e) {
;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
player.paint(g);
}
}
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Color;
public class Player {
public
static final int WIDTH = 50, HEIGHT = 50;
public
Game game;
public
int left, right;
public
int y;
public
int x, xa;
public Player(Game game, int left, int right, int x) {
this.game = game;
this.x = x;
y = game.getHeight() - 20;
this.left = left;
this.right = right;
this.y = y;
x = game.getWidth() - 36;
}
public void update() {
if (x > 0 && x < game.getWidth() - WIDTH - 36)
x += xa;
else if (x == 0)
x++;
else if (x == game.getWidth() - WIDTH - 36)
x--;
}
public void pressed(int keyCode) {
if (keyCode == left)
xa = -1;
else if (keyCode == right)
xa = 1;
}
public void released(int keyCode) {
if (keyCode == left || keyCode == right)
xa = 0;
}
public Rectangle getBounds() {
return new Rectangle(x, y, WIDTH, HEIGHT);
}
public void paint(Graphics g) {
g.fillRect(x, y, WIDTH, HEIGHT);
g.setColor(Color.ORANGE);
}
}
导入java.awt.Color;
导入javax.swing.JFrame;
公共类游戏扩展JFrame{
公众的
最终静态整型宽度=700,高度=450;
公众的
游戏面板;
公共游戏(){
设置尺寸(宽度、高度);
片名(“游戏”);
挫折地面(颜色:白色);
可设置大小(假);
setVisible(真);
setDefaultCloseOperation(关闭时退出);
panel=新游戏面板(此);
添加(面板);
}
公共游戏面板getPanel(){
返回面板;
}
公共静态void main(字符串[]args){
新游戏();
}
}
导入java.awt.Color;
导入java.awt.Graphics;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.KeyEvent;
导入java.awt.event.KeyListener;
导入javax.swing.JPanel;
公共类GamePanel扩展JPanel实现ActionListener、KeyListener{
公众的
游戏;
公众的
玩家;
公共游戏面板(游戏){
挫折背景(颜色:绿色);
这个游戏=游戏;
player=新玩家(game,KeyEvent.VK_左,KeyEvent.VK_右,game.getWidth()-36);
addKeyListener(此);
设置聚焦(真);
}
公众的
无效更新(){
player.update();
}
已执行的公共无效操作(操作事件e){
更新();
重新油漆();
}
公共播放器getPlayer(int playerNo){
返回球员;
}
按下公共无效键(按键事件e){
player.pressed(如getKeyCode());
}
公共无效密钥已释放(密钥事件e){
player.released(如getKeyCode());
}
public void keyTyped(KeyEvent e){
;
}
@凌驾
公共组件(图形g){
超级组件(g);
球员。油漆(g);
}
}
导入java.awt.Graphics;
导入java.awt.Rectangle;
导入java.awt.Color;
公开课选手{
公众的
静态最终整型宽度=50,高度=50;
公众的
游戏;
公众的
int左,右;
公众的
int-y;
公众的
int x,xa;
公共玩家(游戏,整数左,整数右,整数x){
这个游戏=游戏;
这个.x=x;
y=game.getHeight()-20;
this.left=左;
这个。右=右;
这个。y=y;
x=game.getWidth()-36;
}
公共无效更新(){
如果(x>0&&x
TakesetVisible(true)
并将其移动到游戏的最后一个
构造函数。此外,在构建UI时,还应确保您在EDT的上下文中工作,有关更多详细信息,请参阅
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Game extends JFrame {
public final static int WIDTH = 700, HEIGHT = 450;
public GamePanel panel;
public Game() {
setTitle("Game");
setBackground(Color.WHITE);
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new GamePanel(this);
add(panel);
setResizable(false);
setSize(WIDTH, HEIGHT);
setVisible(true);
}
public GamePanel getPanel() {
return panel;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
new Game();
}
});
}
}
基本上,Swing的布局管理是懒惰的,它不会尝试更新容器层次结构,除非您告诉它(revalidate
),或者它实现或调整大小,这是一件好事,因为操作可能会很昂贵
接下来,看看player=newplayer(game,KeyEvent.VK_左,KeyEvent.VK_右,game.getWidth()-36)代码>
您正在将播放机的位置设置为36
像素,小于组件width
,但当调用此选项时,width
将为0
基本上,在进行此类调用之前,您需要允许UI“结算”。这其实不是那么容易。您可以使用ComponentListener
并监视ComponentResistized
事件,但窗口在首次初始化时可以多次调整大小,为此,您需要“等待”直到大小“确定”,例如
public Game() {
addComponentListener(new ComponentAdapter() {
private boolean initalised = false;
private Timer timer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
initalised = true;
panel.init();
timer.stop();
}
});
@Override
public void componentResized(ComponentEvent e) {
if (!initalised) {
timer.restart();
}
}
});
player = new Player(game, KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, game.getWidth() - 36);
public static class Player {
//...
public Player(GamePanel game, int left, int right, int x) {
this.game = game;
this.left = left;
this.right = right;
this.x = x;
y = game.getHeight() - HEIGHT;
}
然后您需要更新GamePanel
以提供init
方法
public class GamePanel extends JPanel implements ActionListener, KeyListener {
public Game game;
public Player player;
public GamePanel(Game game) {
setBackground(Color.GREEN);
this.game = game;
addKeyListener(this);
setFocusable(true);
}
public void init() {
player = new Player(game, KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, game.getWidth() - 36);
repaint();
}
//...
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (player != null) {
player.paint(g);
}
}
}
你有一系列的“神奇”数字,这些数字并不等同于你实际要做的事情,例如
public Game() {
addComponentListener(new ComponentAdapter() {
private boolean initalised = false;
private Timer timer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
initalised = true;
panel.init();
timer.stop();
}
});
@Override
public void componentResized(ComponentEvent e) {
if (!initalised) {
timer.restart();
}
}
});
player = new Player(game, KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, game.getWidth() - 36);
public static class Player {
//...
public Player(GamePanel game, int left, int right, int x) {
this.game = game;
this.left = left;
this.right = right;
this.x = x;
y = game.getHeight() - HEIGHT;
}
这不应该是game.getWidth()-Player.WIDTH
然后在播放器中
public Player(Game game, int left, int right, int x) {
this.game = game;
this.x = x;
y = game.getHeight() - 20;
//...
this.y = y;
x = game.getWidth() - 36;
}
public class Game extends JFrame {
public GamePanel panel;
public Game() {
addComponentListener(new ComponentAdapter() {
private boolean initalised = false;
private Timer timer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
initalised = true;
panel.init();
timer.stop();
}
});
@Override
public void componentResized(ComponentEvent e) {
if (!initalised) {
timer.restart();
}
}
});
setTitle("Game");
setBackground(Color.WHITE);
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new GamePanel(this);
add(panel);
setResizable(false);
pack();
setVisible(true);
}
将参数x
指定给字段x
,然后在构造函数末尾更改它?而且,this.y=y
毫无意义
现在,让我们谈谈设置大小(宽度、高度)的坏主意代码>,这与为什么您的播放机没有显示在您希望的位置有关
窗户有装饰,所以你的可视区域总是小于实际的窗户大小,更糟糕的是,装饰的大小是可变的。相反,您应该使用JFrame#pack
将窗口围绕其内容进行打包,并让内容提供有关其想要的大的提示
请查看以了解更多详细信息
您应该使用pack
,而不是设置帧的大小
public Player(Game game, int left, int right, int x) {
this.game = game;
this.x = x;
y = game.getHeight() - 20;
//...
this.y = y;
x = game.getWidth() - 36;
}
public class Game extends JFrame {
public GamePanel panel;
public Game() {
addComponentListener(new ComponentAdapter() {
private boolean initalised = false;
private Timer timer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
initalised = true;
panel.init();
timer.stop();
}
});
@Override
public void componentResized(ComponentEvent e) {
if (!initalised) {
timer.restart();
}
}
});
setTitle("Game");
setBackground(Color.WHITE);
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new GamePanel(this);
add(panel);
setResizable(false);
pack();
setVisible(true);
}
并允许GamePanel
决定它想要多大
public static class GamePanel extends JPanel implements ActionListener, KeyListener {
public final static int WIDTH = 700, HEIGHT = 450;
public Game game;
public Player player;
public GamePanel(Game game) {
setBackground(Color.GREEN);
this.game = game;
addKeyListener(this);
setFocusable(true);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(WIDTH, HEIGHT);
}
这也意味着,您不应该将Game
传递给对象,而应该将GamePanel
传递给对象并使用其维度,例如
public Game() {
addComponentListener(new ComponentAdapter() {
private boolean initalised = false;
private Timer timer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
initalised = true;
panel.init();
timer.stop();
}
});
@Override
public void componentResized(ComponentEvent e) {
if (!initalised) {
timer.restart();
}
}
});
player = new Player(game, KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, game.getWidth() - 36);
public static class Player {
//...
public Player(GamePanel game, int left, int right, int x) {
this.game = game;
this.left = left;
this.right = right;
this.x = x;
y = game.getHeight() - HEIGHT;
}
您也不应该使用KeyListener
,而应该使用instead,这将解决焦点相关的问题,并使配置按键笔划更容易
基本上,你是