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