我挣扎于 JPanel、getWidth 和 getHeight
I struggle with JPanel, getWidth and getHeight
所以我昨天开始了这个 "Project",我想尝试一个立方体与 windows 边界相撞的程序。看起来很简单。
然而,我在边界上挣扎。我似乎无法在 window 的右侧和底部找到 "perfect" collison。立方体总是比预期走得更远。
我认为问题与我设置 window 大小的方式有关?我不确定,但我确实尝试了一些更改,但没有奏效。
代码如下:
package spritesInJava;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.ImageObserver;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Game {
public static JFrame myGame;
public static Timer timer;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createGame();
timer.start();
}
});
}
public static void createGame() {
myGame = new JFrame("Felicia");
myGame.add(new MyPanel());
myGame.pack();
myGame.setSize(new Dimension(1000,1000));
myGame.setPreferredSize(new Dimension(1000,1000));
myGame.setVisible(true);
myGame.setDefaultCloseOperation(1);
MyPanel.loadImage();
}
}
class MyPanel extends JPanel implements ActionListener {
private static Image image; //Sprite
private static final long serialVersionUID = 1251340649341903871L;
private static ImageObserver observer;
private int x = 50;
private int y = 50;
private int width = 200;
private int height = 100;
private int speedx = 2;
private int speedy = 2;
MyPanel() {
Game.timer = new Timer(10,this);
}
@Override
public void actionPerformed(ActionEvent e) {
int screenWidth = Game.myGame.getWidth();
int screenHeight = Game.myGame.getHeight();
x+=speedx;
y+=speedy;
if(x >= screenWidth - width) {
speedx = -speedx;
}
else if(x < 0 ) {
speedx = -speedx;
}
if(y >= screenHeight- height ) {
speedy = -speedy;
}
else if(y < 0 ) {
speedy = -speedy;
}
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
//g.drawImage(image, x, y,width,height,observer); //Uses the image that was loaded below and draws it.
g.fillRect(x, y, width, height);
}
public static void loadImage() { //Load the image
ImageIcon icon = new ImageIcon("photos/Felicia.png");
image = icon.getImage(); //Set the "temp" ImageIcon icon to the public ImageIcon
}
}
立方体应该击中 4 个边界之一,然后变为“-speed”,因此如果速度为 5,则速度应为完全相反(负)并转向另一方向。这行得通,但为时已晚。我做的碰撞系统好像不行
很抱歉将所有代码放在一个文件中 class!
提前致谢!
所以,马上,这似乎是错误的...
myGame.add(new MyPanel());
myGame.pack();
myGame.setSize(new Dimension(1000, 1000));
myGame.setPreferredSize(new Dimension(1000, 1000));
myGame.setVisible(true);
您 pack
window 之前的首选尺寸是 set/determined,这意味着 window 将希望采用尽可能小的尺寸(因为 [=内容的19=]默认为0x0
)。
作为一般规则,您应该避免调用 setPreferredSize
,但我会特别避免在 JFrame
.
上使用它
为什么?因为JFrame
有装饰(window 标题和边框),它们被插入window,所以可见尺寸实际上是frameSize - decorationInsets
,这成为你问题的核心稍后。
因此,我将覆盖 MyPanel
中的 getPreferredSize
并指定组件的 "viewable" 范围
class MyPanel extends JPanel implements ActionListener {
//...
@Override
public Dimension getPreferredSize() {
return new Dimension(1000, 1000);
}
然后在你的 main class 你可以做...
myGame = new JFrame("Felicia");
myGame.add(new MyPanel());
myGame.pack();
myGame.setVisible(true);
API 会为您解决。
好的,进入下一期...
public void actionPerformed(ActionEvent e) {
int screenWidth = Game.myGame.getWidth();
int screenHeight = Game.myGame.getHeight();
Game.myGame
是 JFrame
,你要求的是 window 尺寸,但正如我之前所说,框架有装饰,嵌入框架中,减少了您的组件可用的可视区域。相反,您应该使用组件本身的大小
public void actionPerformed(ActionEvent e) {
int screenWidth = getWidth();
int screenHeight = getHeight();
一些建议...
我认为需要这些...
public static JFrame myGame;
public static Timer timer;
但我在使用 static
时遇到问题 ;)。使 myGame
static
成为 "easy" 以从代码中的位置访问它的功能,这些位置对此不承担任何责任。
在这种情况下 Timer
是有争议的,但我可能想要一个 "update engine" 来封装它和过度更新工作流程,但这就是我 ;)
我认为这不是必需的(static
)
public static void loadImage() { //Load the image
ImageIcon icon = new ImageIcon("photos/Felicia.png");
image = icon.getImage(); //Set the "temp" ImageIcon icon to the public ImageIcon
}
功能应该在组件创建时由组件本身创建(或通过其他 "setup" 阶段)。我也鼓励使用 ImageIO.read
,因为它会在出现问题时生成 IOException
,这与 ImageIcon
不同,后者会静默失败。
作为(ImageIO.read
)的附带好处,您还将知道图像何时完成加载,因为该方法不会 return 直到它完成,这意味着您不必冒险一些空框。
你不需要...
private static ImageObserver observer;
也不需要是 static
(因为 private
它会破坏任何好处),但是,JPanel
实际上是一个 ImageObserver
,所以你可以将 this
传递给 drawImage
所以我昨天开始了这个 "Project",我想尝试一个立方体与 windows 边界相撞的程序。看起来很简单。
然而,我在边界上挣扎。我似乎无法在 window 的右侧和底部找到 "perfect" collison。立方体总是比预期走得更远。
我认为问题与我设置 window 大小的方式有关?我不确定,但我确实尝试了一些更改,但没有奏效。
代码如下:
package spritesInJava;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.ImageObserver;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Game {
public static JFrame myGame;
public static Timer timer;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createGame();
timer.start();
}
});
}
public static void createGame() {
myGame = new JFrame("Felicia");
myGame.add(new MyPanel());
myGame.pack();
myGame.setSize(new Dimension(1000,1000));
myGame.setPreferredSize(new Dimension(1000,1000));
myGame.setVisible(true);
myGame.setDefaultCloseOperation(1);
MyPanel.loadImage();
}
}
class MyPanel extends JPanel implements ActionListener {
private static Image image; //Sprite
private static final long serialVersionUID = 1251340649341903871L;
private static ImageObserver observer;
private int x = 50;
private int y = 50;
private int width = 200;
private int height = 100;
private int speedx = 2;
private int speedy = 2;
MyPanel() {
Game.timer = new Timer(10,this);
}
@Override
public void actionPerformed(ActionEvent e) {
int screenWidth = Game.myGame.getWidth();
int screenHeight = Game.myGame.getHeight();
x+=speedx;
y+=speedy;
if(x >= screenWidth - width) {
speedx = -speedx;
}
else if(x < 0 ) {
speedx = -speedx;
}
if(y >= screenHeight- height ) {
speedy = -speedy;
}
else if(y < 0 ) {
speedy = -speedy;
}
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
//g.drawImage(image, x, y,width,height,observer); //Uses the image that was loaded below and draws it.
g.fillRect(x, y, width, height);
}
public static void loadImage() { //Load the image
ImageIcon icon = new ImageIcon("photos/Felicia.png");
image = icon.getImage(); //Set the "temp" ImageIcon icon to the public ImageIcon
}
}
立方体应该击中 4 个边界之一,然后变为“-speed”,因此如果速度为 5,则速度应为完全相反(负)并转向另一方向。这行得通,但为时已晚。我做的碰撞系统好像不行
很抱歉将所有代码放在一个文件中 class!
提前致谢!
所以,马上,这似乎是错误的...
myGame.add(new MyPanel());
myGame.pack();
myGame.setSize(new Dimension(1000, 1000));
myGame.setPreferredSize(new Dimension(1000, 1000));
myGame.setVisible(true);
您 pack
window 之前的首选尺寸是 set/determined,这意味着 window 将希望采用尽可能小的尺寸(因为 [=内容的19=]默认为0x0
)。
作为一般规则,您应该避免调用 setPreferredSize
,但我会特别避免在 JFrame
.
为什么?因为JFrame
有装饰(window 标题和边框),它们被插入window,所以可见尺寸实际上是frameSize - decorationInsets
,这成为你问题的核心稍后。
因此,我将覆盖 MyPanel
中的 getPreferredSize
并指定组件的 "viewable" 范围
class MyPanel extends JPanel implements ActionListener {
//...
@Override
public Dimension getPreferredSize() {
return new Dimension(1000, 1000);
}
然后在你的 main class 你可以做...
myGame = new JFrame("Felicia");
myGame.add(new MyPanel());
myGame.pack();
myGame.setVisible(true);
API 会为您解决。
好的,进入下一期...
public void actionPerformed(ActionEvent e) {
int screenWidth = Game.myGame.getWidth();
int screenHeight = Game.myGame.getHeight();
Game.myGame
是 JFrame
,你要求的是 window 尺寸,但正如我之前所说,框架有装饰,嵌入框架中,减少了您的组件可用的可视区域。相反,您应该使用组件本身的大小
public void actionPerformed(ActionEvent e) {
int screenWidth = getWidth();
int screenHeight = getHeight();
一些建议...
我认为需要这些...
public static JFrame myGame;
public static Timer timer;
但我在使用 static
时遇到问题 ;)。使 myGame
static
成为 "easy" 以从代码中的位置访问它的功能,这些位置对此不承担任何责任。
在这种情况下 Timer
是有争议的,但我可能想要一个 "update engine" 来封装它和过度更新工作流程,但这就是我 ;)
我认为这不是必需的(static
)
public static void loadImage() { //Load the image
ImageIcon icon = new ImageIcon("photos/Felicia.png");
image = icon.getImage(); //Set the "temp" ImageIcon icon to the public ImageIcon
}
功能应该在组件创建时由组件本身创建(或通过其他 "setup" 阶段)。我也鼓励使用 ImageIO.read
,因为它会在出现问题时生成 IOException
,这与 ImageIcon
不同,后者会静默失败。
作为(ImageIO.read
)的附带好处,您还将知道图像何时完成加载,因为该方法不会 return 直到它完成,这意味着您不必冒险一些空框。
你不需要...
private static ImageObserver observer;
也不需要是 static
(因为 private
它会破坏任何好处),但是,JPanel
实际上是一个 ImageObserver
,所以你可以将 this
传递给 drawImage