Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/387.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JPanel宽度超过getPreferredSize()中定义的维度_Java_Swing_Graphics2d - Fatal编程技术网

Java JPanel宽度超过getPreferredSize()中定义的维度

Java JPanel宽度超过getPreferredSize()中定义的维度,java,swing,graphics2d,Java,Swing,Graphics2d,我试图创建一个突破游戏,但我发现了一个关于游戏“场景”面板大小的恼人问题 这是我的Board类,它是游戏所有组件分布的面板: import java.awt.*; import java.awt.event.*; import javax.swing.*; class Board extends JPanel { private static final long serialVersionUID = 1L; public final int WIDTH = 400;

我试图创建一个突破游戏,但我发现了一个关于游戏“场景”面板大小的恼人问题

这是我的
Board
类,它是游戏所有组件分布的面板:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class Board extends JPanel {

    private static final long serialVersionUID = 1L;
    public final int WIDTH = 400;
    public final int HEIGHT = 300;
    private final int UPDATE_INTERVAL = 20;

    private Timer timer;
    public Ball ball;
    public Paddle paddle;

    private JLabel scoreLabel, score;   

    public Board() {

        paddle = new Paddle(this);
        ball = new Ball(this);

        setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));

        scoreLabel = new JLabel("Score: ");
        scoreLabel.setFont(getFont().deriveFont(12f));
        score = new JLabel();
        score.setFont(getFont().deriveFont(12f));
        this.add(scoreLabel);
        this.add(score);

        this.addKeyListener(new KeyAdapter() {

            @Override
            public void keyPressed(KeyEvent e) {
                paddle.keyPressed(e);
                if (e.getKeyCode() == KeyEvent.VK_SPACE){
                    starGame();
                }
            }

            @Override
            public void keyReleased(KeyEvent e) {
                paddle.keyReleased(e);
            }
        });

        ActionListener action = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                updateBoard();
                repaint();
            }
        };

        timer = new Timer(UPDATE_INTERVAL, action);

        setFocusable(true);

    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(WIDTH, HEIGHT);
    }

    private void updateBoard() {
        ball.move();
        paddle.move();
        repaint();
    }

    public void gameOver() {
        JOptionPane.showMessageDialog(this, "Game Over");
        newGame();
    }

    public void starGame() {
        timer.start();
    }

    public void stop() {
        timer.stop();
    }

    public void newGame() {
        stop();
        paddle = new Paddle(this);
        ball = new Ball(this);
        repaint();
    }

    public void setSpeed(int speed) {
        ball.setSpeed(speed);
    }


    @Override
    protected void paintComponent(Graphics g) {

        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        ball.paint(g2);
        paddle.paint(g2);
    }
}
在上面的代码中,可以看到我基于固定值设置了宽度和高度,并重写了
preferredSize()
方法以符合这些度量

问题在于,屏幕边缘的碰撞逻辑是基于我在
JPanel
中设置的测量值,但出于某种原因,它在右侧获得了一个额外的空间,如下面gif中右角的球和桨的碰撞所示:

我认为问题可能与有关,但额外的空间出现在
JPanel

在Ball类中,我用于检测右角边界以反转方向的公式位于两个类的
move()
方法中:

import java.awt.Graphics2D;
import java.awt.Rectangle;

public class Ball {

    private int x = 0;
    private int y = 15;
    private final int DIAMETER = 30;
    private int xSpeed = 1;
    private int ySpeed = 1;

    private final Board board;
    private final Paddle paddle;


    public Ball(Board board) {
        this.board = board;
        this.paddle = board.paddle;
        y = paddle.getTopY() - DIAMETER;
        x = board.WIDTH / 2 - DIAMETER / 2;
    }

    public void move() {

        if (x >= board.WIDTH - DIAMETER || x <= 0) {
            xSpeed = -xSpeed;
        }

        if (y < 15) {
            ySpeed = -ySpeed;
        }

        if (y + DIAMETER > paddle.getTopY() + paddle.HEIGHT) {
            board.gameOver();
        }

        if (collision()) {

            float paddleCenter = paddle.getX() + (paddle.WIDTH/2);

            float relativePos = (this.x + (DIAMETER/2) - paddleCenter) / (paddle.WIDTH/2);

            if((relativePos > 0 && xSpeed < 0) || (relativePos < 0 && xSpeed > 0)){
                xSpeed = -xSpeed;
            }

            ySpeed = -ySpeed;
            y = paddle.getTopY() - DIAMETER;
        }

        x += xSpeed;
        y += ySpeed;
    }

     [...]
}
导入java.awt.Graphics2D;
导入java.awt.Rectangle;
公共班级舞会{
私有整数x=0;
私人智力y=15;
专用最终内径=30;
私有int xSpeed=1;
私用int-ySpeed=1;
私人终审委员会;
私人决赛;
公众舞会(董事会){
this.board=董事会;
this.paile=board.paile;
y=桨。getTopY()-直径;
x=板宽/2-直径/2;
}
公开作废动议(){
如果(x>=board.WIDTH-DIAMETER | | x paile.getTopY()+paile.HEIGHT){
board.gameOver();
}
if(碰撞()){
浮动桨中心=桨.getX()+(桨.WIDTH/2);
浮动相对速度=此.x+(直径/2)-桨叶中心/(桨叶宽度/2);
if((相对速度>0&&xSpeed<0)| |(相对速度<0&&xSpeed>0)){
xSpeed=-xSpeed;
}
ySpeed=-ySpeed;
y=桨。getTopY()-直径;
}
x+=x速度;
y+=y速度;
}
[...]
}
班级桨:

import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;

public class Paddle {

    private int x = 0;
    private final int topY;
    public final int WIDTH = 100;
    public final int HEIGHT = 10;
    private int direction = 0;

    private Board board;

    public Paddle(Board board) {
        this.board = board;
        topY = board.HEIGHT;
        x = board.WIDTH / 2 - WIDTH / 2;

    }

    public void move() {
        if (x + direction >= 0 && x + direction <= board.WIDTH - WIDTH) {
            x = x + direction;
        }
    }

    public void paint(Graphics2D g2) {
        g2.fillRect(x, topY, WIDTH, HEIGHT);
    }

    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_LEFT) {
            direction = -5;
        }
        if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
            direction = 5;
        }
    }

    public void keyReleased(KeyEvent e) {
        direction = 0;
    }

    public Rectangle getBounds() {
        return new Rectangle(x, topY, WIDTH, HEIGHT);
    }

    public int getTopY() {
        return topY;
    }

    public int getX() {
        return x;
    }
}
导入java.awt.Graphics2D;
导入java.awt.Rectangle;
导入java.awt.event.KeyEvent;
公务舱桨{
私有整数x=0;
私人终审法院;
公共最终整数宽度=100;
公共最终内部高度=10;
私有int方向=0;
私人董事会;
公共挡板(板){
this.board=董事会;
topY=板高度;
x=板宽/2-宽度/2;
}
公开作废动议(){

如果(x+方向>=0&&x+方向我们不知道应用程序是如何构建的。例如,您是否直接将板面板添加到框架中?或者您将板面板嵌套到另一个面板中,并且看到的额外空间来自父面板

您是否尝试将
LineBorder
添加到板面板。如果边框绘制正确,但球仍然没有到达边缘,则说明碰撞逻辑有问题

setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
这是没有意义的,因为你正在做球和桨的自定义绘制。如果有任何布局应该为空

编辑:

这看起来很可疑:

frame.pack(); 
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
frame.setLocationRelativeTo(null); 
frame.setResizable(false); 
frame.setVisible(true);
打包()框架,然后更改框架的属性。由于框架不可调整大小,因此无需绘制边框,因此边框的额外宽度现在添加到面板中,但逻辑检查的是硬编码值,而不是面板的实际宽度

代码应为:

//frame.pack(); 
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
frame.setLocationRelativeTo(null); 
frame.setResizable(false); 
frame.pack(); 
frame.setVisible(true);
请注意,问题与您发布的代码无关


这就是为什么一个合适的
MCVE
应该与每个问题一起发布在论坛上,而不是发布在另一个网站上!!!

作为一个可测试的片段,问题会很大,
-为什么?桨类与问题无关。你所需要的只是板、球和框架。菜单栏也不相关。问题的关键是f或者你可以简化代码,以便专注于与问题直接相关的逻辑。
要点中的示例是最小的、完整的、可验证的示例,只是
-不,这是整个应用程序的转储。你的问题是球以及它如何在面板侧反弹。其他代码与你的问题无关。我已经给了你一些不必要代码的例子。
MCVE
的目的是简化问题。我们没有时间看几百行代码。所以你简化了代码,使它仍然可以执行。@camickr同样的问题也会影响到桨类。因此,我添加了Ball、patle和Board类。There是所有三个类中的更多代码,我删除了它以简化执行。仅供将来参考FlowLayout是JPanels的默认布局,无需将其设置为该布局。Board类被添加为“contentpane”当然是JFrame。只要在窗口中有这个JPanel。我在JPanel中为score添加了2个JLabel,所以我使用了这个布局。标签可能应该在添加到框架的页面开始的单独面板上。在任何情况下,如果您验证了面板的边框是正确的,那么正如我所说的,问题是您的冲突检测逻辑。So您只需要进行基本调试。逐步完成逻辑,确保所有变量的值都是您期望的值。显然,您在某个地方存在边界问题。@diegofm,您还可以查看:对于一些球动画。只需将球的数量更改为1,以查看其反应。球的边缘始终接触到球的侧面面板。你甚至可以调整框架的大小。因此,这里使用的逻辑可能有助于发现你的逻辑问题。我在move方法中使用的逻辑与你在这段代码中使用的逻辑相同。为了进行测试,我在JPanel内画了一个宽度为400的小矩形,并且还有一个空格。球忽略了相同的空格。