将移动对象添加到 JFrame
Add moving objects to JFrame
我正在创建一个 java 游戏。游戏中有英雄和泡泡。当我按下箭头键时,英雄应该移动,而泡泡应该有连续的对角线移动。当我将英雄或气泡分别直接添加到 JFrame
时,我得到了所需的行为,但是当我将它们都添加时,我只得到一个非常小的正方形!我尝试将它们添加到相同的 JPanel
,然后将 JPanel
添加到 JFrame
,但它不起作用。可能我必须为 JPanel
定义某种类型的布局。
我做错了什么?
代码:
public class Pang {
public static void main(String[] args) {
JFrame f=new JFrame();
JPanel gamePanel=new JPanel();
gamePanel.setPreferredSize(new Dimension(800, 600));
DrawHero d=new DrawHero();
DrawBubble bubble=new DrawBubble();
gamePanel.add(d);
gamePanel.add(bubble);
f.add(gamePanel);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(800, 600);
}
}
public class DrawHero extends JPanel implements ActionListener, KeyListener {
Timer myTimer = new Timer(5, this);
int x = 0, y = 0, dx = 0, dy = 0, step = 10;
private transient Image imageHero = null;
public DrawHero() {
myTimer.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
imageHero = getHeroImage();
g2.drawImage(imageHero, x, y, 40, 40, null);
}
public Image getHeroImage() {
Image image = null;
image = getImage("hero.png");
return image;
}
public Image getImage(String path) {
Image tempImage = null;
try {
URL heroiURL = DrawHero.class.getResource(path);
tempImage = Toolkit.getDefaultToolkit().getImage(heroiURL);
} catch (Exception e) {
System.out.println("Error loading hero image! - "
+ e.getMessage());
}
return tempImage;
}
public void actionPerformed(ActionEvent e) {
repaint();
}
public void moveUp() {
y = y - step;
}
public void moveDown() {
y = y + step;
}
public void moveLeft() {
x = x - step;
}
public void moveRight() {
x = x + step;
}
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_UP) {
moveUp();
}
if (keyCode == KeyEvent.VK_DOWN) {
moveDown();
}
if (keyCode == KeyEvent.VK_LEFT) {
moveLeft();
}
if (keyCode == KeyEvent.VK_RIGHT) {
moveRight();
}
}
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
}
public class DrawBubble extends JPanel implements ActionListener, KeyListener {
Timer myTimer = new Timer(5, this);
int x = 100, y = 200, dx = 0, dy = 0, step = 10;
private transient Image imageHero = null;
public DrawBubble() {
myTimer.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.fill(new Ellipse2D.Double(x, y, 40, 40));
}
public void actionPerformed(ActionEvent e) {
x=x+dx;
y=y+dy;
repaint();
}
public void moveBubble() {
dy=2;
dx=2;
}
public void keyPressed(KeyEvent e) {
moveBubble();
}
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
}
When I add the hero or the bubble directly into to the JFrame separately I get the desired behavior, but when I add them both i just get a very small square!
JFrame 的默认布局管理器是 BorderLayout。当您在没有约束的情况下使用 add(component) 时,组件将转到 CENTER。 CENTER只能添加一个组件,所以只显示最后添加的一个。
I tried to add them to the same JPanel and after add that JPanel to the JFrame but it is not working.
JPanel 的默认布局管理器是遵循组件首选大小的 FlowLayout。问题是你没有重写 getPreferredSize()
方法,所以大小是 (0, 0) 并且没有什么可绘制的。
Probably I have to define some type of layout to the JPanels.
实际上,由于您想要随机运动,因此需要在面板上使用空布局,然后使用组件的 setSize()
和 setLocation()
方法来定位组件。
那么当您执行此操作时,自定义绘制应始终在 (0, 0) 而不是 (x, y) 处完成,因为该位置将控制组件在面板上绘制的位置。
我建议 DrawHero
和 DrawBubble
(应分别称为 Hero
或 Bubble
)都不应扩展任何 JComponent
。相反,每个人都应该知道如何在请求时将自己绘制到传递给它的 Graphics
对象。
然后单个 GameField
或 PlayingArea
class 应该保留对所有 Bubble
对象和 Hero
的引用并绘制调用 draw(Graphics)
那些对象的方法。
使用这种方法不必担心 GameField
组件内的布局(它们变得无关紧要)。
这是我在 this answer to [Collision detection with complex shapes 中渲染静止物体所追求的基本策略。
我正在创建一个 java 游戏。游戏中有英雄和泡泡。当我按下箭头键时,英雄应该移动,而泡泡应该有连续的对角线移动。当我将英雄或气泡分别直接添加到 JFrame
时,我得到了所需的行为,但是当我将它们都添加时,我只得到一个非常小的正方形!我尝试将它们添加到相同的 JPanel
,然后将 JPanel
添加到 JFrame
,但它不起作用。可能我必须为 JPanel
定义某种类型的布局。
我做错了什么?
代码:
public class Pang {
public static void main(String[] args) {
JFrame f=new JFrame();
JPanel gamePanel=new JPanel();
gamePanel.setPreferredSize(new Dimension(800, 600));
DrawHero d=new DrawHero();
DrawBubble bubble=new DrawBubble();
gamePanel.add(d);
gamePanel.add(bubble);
f.add(gamePanel);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(800, 600);
}
}
public class DrawHero extends JPanel implements ActionListener, KeyListener {
Timer myTimer = new Timer(5, this);
int x = 0, y = 0, dx = 0, dy = 0, step = 10;
private transient Image imageHero = null;
public DrawHero() {
myTimer.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
imageHero = getHeroImage();
g2.drawImage(imageHero, x, y, 40, 40, null);
}
public Image getHeroImage() {
Image image = null;
image = getImage("hero.png");
return image;
}
public Image getImage(String path) {
Image tempImage = null;
try {
URL heroiURL = DrawHero.class.getResource(path);
tempImage = Toolkit.getDefaultToolkit().getImage(heroiURL);
} catch (Exception e) {
System.out.println("Error loading hero image! - "
+ e.getMessage());
}
return tempImage;
}
public void actionPerformed(ActionEvent e) {
repaint();
}
public void moveUp() {
y = y - step;
}
public void moveDown() {
y = y + step;
}
public void moveLeft() {
x = x - step;
}
public void moveRight() {
x = x + step;
}
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_UP) {
moveUp();
}
if (keyCode == KeyEvent.VK_DOWN) {
moveDown();
}
if (keyCode == KeyEvent.VK_LEFT) {
moveLeft();
}
if (keyCode == KeyEvent.VK_RIGHT) {
moveRight();
}
}
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
}
public class DrawBubble extends JPanel implements ActionListener, KeyListener {
Timer myTimer = new Timer(5, this);
int x = 100, y = 200, dx = 0, dy = 0, step = 10;
private transient Image imageHero = null;
public DrawBubble() {
myTimer.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.fill(new Ellipse2D.Double(x, y, 40, 40));
}
public void actionPerformed(ActionEvent e) {
x=x+dx;
y=y+dy;
repaint();
}
public void moveBubble() {
dy=2;
dx=2;
}
public void keyPressed(KeyEvent e) {
moveBubble();
}
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
}
When I add the hero or the bubble directly into to the JFrame separately I get the desired behavior, but when I add them both i just get a very small square!
JFrame 的默认布局管理器是 BorderLayout。当您在没有约束的情况下使用 add(component) 时,组件将转到 CENTER。 CENTER只能添加一个组件,所以只显示最后添加的一个。
I tried to add them to the same JPanel and after add that JPanel to the JFrame but it is not working.
JPanel 的默认布局管理器是遵循组件首选大小的 FlowLayout。问题是你没有重写 getPreferredSize()
方法,所以大小是 (0, 0) 并且没有什么可绘制的。
Probably I have to define some type of layout to the JPanels.
实际上,由于您想要随机运动,因此需要在面板上使用空布局,然后使用组件的 setSize()
和 setLocation()
方法来定位组件。
那么当您执行此操作时,自定义绘制应始终在 (0, 0) 而不是 (x, y) 处完成,因为该位置将控制组件在面板上绘制的位置。
我建议 DrawHero
和 DrawBubble
(应分别称为 Hero
或 Bubble
)都不应扩展任何 JComponent
。相反,每个人都应该知道如何在请求时将自己绘制到传递给它的 Graphics
对象。
然后单个 GameField
或 PlayingArea
class 应该保留对所有 Bubble
对象和 Hero
的引用并绘制调用 draw(Graphics)
那些对象的方法。
使用这种方法不必担心 GameField
组件内的布局(它们变得无关紧要)。
这是我在 this answer to [Collision detection with complex shapes 中渲染静止物体所追求的基本策略。