Java JFrame getHeight()和getWidth()返回0
我在做一个简单的乒乓球游戏;部分碰撞机制需要获得画布的宽度和高度来重定向球。但是,Java JFrame getHeight()和getWidth()返回0,java,swing,jpanel,paint,thread-sleep,Java,Swing,Jpanel,Paint,Thread Sleep,我在做一个简单的乒乓球游戏;部分碰撞机制需要获得画布的宽度和高度来重定向球。但是,getWidth()和getHeight()由于某些原因返回0。这是主要的代码块 package pong; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class Main extends JPanel { static int gameSpeed = 10; Ball ball = new
getWidth()
和getHeight()
由于某些原因返回0。这是主要的代码块
package pong;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main extends JPanel {
static int gameSpeed = 10;
Ball ball = new Ball(this);
private void move() {
ball.move();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
ball.paint(g2d);
}
public static void main(String args[]) throws InterruptedException {
JFrame frame = new JFrame("Pong");
Main game = new Main();
frame.add(game);
frame.setSize(400, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while (true) {
game.move();
game.repaint();
Thread.sleep(gameSpeed);
}
}
}
这里是实际的Ball
类,它处理移动条件
package pong;
import javax.swing.*;
import java.awt.*;
public class Ball extends JPanel {
int x = 1;
int y = 1;
int dx = 1;
int dy = 1;
private Main game;
public Ball(Main game) {
this.game = game;
}
void move() {
System.out.println(getWidth() + getHeight());
if (x + dx < 0) {
dx = 1;
}
if (y + dy < 0) {
dy = 1;
}
if (x + dx > (getWidth() - 30)) {
dx = -1;
}
if (y + dy > (getHeight() - 30)) {
dy = -1;
}
x = x + dx;
y = y + dy;
}
public void paint(Graphics2D g) {
g.fillOval(x, y, 30, 30);
}
}
package-pong;
导入javax.swing.*;
导入java.awt.*;
公共班级舞会{
int x=1;
int y=1;
int dx=1;
int-dy=1;
私人主游戏;
公众球(主要比赛){
这个游戏=游戏;
}
无效移动(){
System.out.println(getWidth()+getHeight());
如果(x+dx<0){
dx=1;
}
if(y+dy<0){
dy=1;
}
如果(x+dx>(getWidth()-30)){
dx=-1;
}
如果(y+dy>(getHeight()-30)){
dy=-1;
}
x=x+dx;
y=y+dy;
}
公共空隙涂料(图2D g){
g、 椭圆形(x,y,30,30);
}
}
编辑:问题解决了,我只是没有告诉getWidth()和getHeight()应该指什么。显然,如果我不告诉他们得到什么,他们会返回null。德普。简单的修复方法是将它们更改为game.getWidth()和game.getHeight()。不过,谢谢你的帮助!您的所有投入在其他领域也有帮助。:)
Graphics
/Java2D
默认情况下从不重新计算合理的维度
,结果为零维度
,您必须为JPanel
覆盖getPreferredSize
,然后getWidth/Height
将为JPanel的大小返回正确的坐标JFrame.pack()
代替任何大小调整paintComponent
内部覆盖Swing JComponents
的paintComponent
,而不是paintComponent()
。代码行应为super.paintComponent
,否则将累积绘制Swing
中使用Thread.sleep(int)
,也不要在Java7和Swing中使用Swing计时器
而使用Thread.sleep(int)
停止的无休止循环这是一个复杂的问题,由于一些设计决策而变得更糟 通常,Swing希望在布局管理器的约束范围内使用组件。布局管理器需要一定数量的信息才能决定如何最好地布局这些组件。这包括
getPreferred/Minimum/Maximum
size
问题是您实际上不想使用布局管理器,因为您想手动定位球。当您扔掉布局管理器时,您将负责大量工作,确保组件在父容器中的大小和位置正确
一个更简单的解决方案是生成一个“游戏”表面,您可以在上面绘制游戏元素或实体
问题是,您似乎不知道要使用哪种方法。您的Ball
是从JPanel
扩展而来的,但您的主面板正在绘制自身…这不是组件的渲染方式
您可以简单地使用Main
作为主要游戏界面,并将所有实体直接呈现给它,而不是使用组件作为游戏实体的基础(这会带来许多问题和管理开销)。这使您能够更好地控制并简化流程-IMHO
例如
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main extends JPanel {
public static final int GAME_SPEED = 40;
Ball ball = new Ball();
protected void move() {
ball.move(this);
}
public Main() {
setLayout(null);
Timer timer = new Timer(GAME_SPEED, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
move();
repaint();
}
});
timer.start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
ball.paint((Graphics2D)g);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
public static void main(String args[]) throws InterruptedException {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Pong");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Main game = new Main();
frame.add(game);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
public interface Entity {
public void paint(Graphics2D g2d);
public Rectangle getBounds();
}
public interface MovableEntity extends Entity {
public void move(Container parent);
}
public class Ball implements MovableEntity {
private int dx = 1;
private int dy = 1;
private int x;
private int y;
@Override
public void move(Container parent) {
int width = parent.getWidth();
int height = parent.getHeight();
int x = getX();
int y = getY();
x += dx;
y += dy;
if (x + dx < 0) {
dx = 1;
}
if (y + dy < 0) {
dy = 1;
}
if (x + dx > (width - getBounds().width)) {
dx = -1;
}
if (y + dy > (height - getBounds().height)) {
dy = -1;
}
setLocation(x, y);
}
@Override
public void paint(Graphics2D g2d) {
int width = getBounds().width;
int height = getBounds().height;
int dim = Math.min(width, height);
int xPos = x + ((width - dim) / 2);
int yPos = y + ((height - dim) / 2);
g2d.fillOval(xPos, yPos, dim, dim);
}
@Override
public Rectangle getBounds() {
return new Rectangle(x, y, 30, 30);
}
}
}
导入java.awt.Container;
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.Rectangle;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.Timer;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
公共类Main扩展了JPanel{
公共静态最终整数游戏_速度=40;
球=新球();
受保护的无效移动(){
球。移动(这个);
}
公用干管(){
setLayout(空);
计时器计时器=新计时器(游戏速度,新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
move();
重新油漆();
}
});
timer.start();
}
@凌驾
受保护组件(图形g){
超级组件(g);
球形油漆((图2d)g);
}
@凌驾
公共维度getPreferredSize(){
返回新维度(400400);
}
公共静态void main(字符串args[])引发InterruptedException{
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
}
JFrame=新JFrame(“Pong”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
主游戏=新主游戏();
frame.add(游戏);
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
公共接口实体{
公共空隙涂料(Graphics2D g2d);
公共矩形getBounds();
}
公共接口MovableEntity扩展实体{
公共无效移动(容器父级);
}
公共类Ball实现了MovableEntity{
私有整数dx=1;
私有整数dy=1;
私人INTX;
私营企业;
@凌驾
公共v