【问题标题】:ball goes off the screen球离开屏幕
【发布时间】:2026-01-05 04:15:02
【问题描述】:

我一直在尝试制作一个弹跳球动画。除了一件事,我什么都做对了。 一旦击中框架的下层和框架的右侧,球就会离开屏幕。

我设置的条件如下:

if( x_Pos > frameWidth - ballRadius)
  // turn the ball back
if( y_Pos > frameHeight - ballRadius)
  // turn the ball back

但是当球击中框架的下层和右层时,它会消失一段时间。 这是最终会发生的事情:

在第二张图片中,球击中了下层甲板并消失了一段时间。 为什么会发生这种情况?

如果这是我的完整代码:

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

class MovingBall2D extends JPanel{

 int x_Pos=0;
 int y_Pos=30;
 int speedX=1;
 int speedY=1;
 int diameter=30;
 int height=30;
 int frameX=700;
 int frameY=200;
 int radius=diameter/2;

 MovingBall2D() {
  this.setSize(frameX,frameY);
  ActionListener taskPerformer = new ActionListener() {
   public void actionPerformed(ActionEvent ae) {
     if(x_Pos < 0) {
      x_Pos = 0;
      speedX = 1;
     }
     else if( x_Pos >= ( frameX - radius ) ) {
      x_Pos =  frameX - diameter;
      speedX = -1; 
     }
     if(y_Pos < 0) {
      y_Pos = 0;
      speedY = 1;
     }
     else if( y_Pos >= ( frameY - radius ) ) {
      y_Pos =  frameY - radius; 
      speedY = -1;
     } 
     x_Pos = x_Pos + speedX;
     y_Pos = y_Pos + speedY;    
     repaint();
    }
   };
    new Timer(4,taskPerformer).start();
  }

   public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(Color.black);
    g.fillRect(0,0,frameX,frameY);
    g.setColor(Color.red);
    g.fillOval(x_Pos , y_Pos , diameter , height);
   }
  }

   class Main2D {
    Main2D() {
     JFrame fr=new JFrame();
     MovingBall2D o = new MovingBall2D();
     fr.add(o);
     fr.setSize(600,200);
     fr.setVisible(true);
     fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    } 

     public static void main(String args[]) {
        new Main2D();
     }
     }  

【问题讨论】:

    标签: java swing user-interface graphics 2d


    【解决方案1】:

    基本上这是因为您将 JFrame 设置为 200 像素高,这意味着您的面板将具有更小的高度(减去标题和边框)。

    另外你的球从(xpos, ypos)延伸到(xpos+diameter,ypos+diameter),因此正确的条件应该是y_Pos &gt; frameHeight - ballDiameter而不是y_Pos &gt; frameHeight - ballRadius

    【讨论】:

    • 你能详细说明一下Basically it is because you set your JFrame to be 200 px tall which then means that your panel will have less height (minus title and borders).这一行吗
    • 您将 JFrame 的大小设置为绝对 200 像素(测量的完整高度,包括标题)。这意味着您的组件内部的高度小于 200 像素(因为边框也占用了一些空间)。在您的代码中,您假设组件始终为 200px 高,但事实并非如此。
    • @Howard 这个东西y_Pos &gt; frameHeight - ballDiameter 不起作用。球仍然稍微低于框架。 如何知道绘图区/面板的实际宽度和高度?
    • @Howard 你能解释一下电话吗MovingBall2D.this.getHeight()
    【解决方案2】:

    您使用的框架宽度(700)似乎大于组件的实际尺寸(600)。使用 JPanel.getWidth() 和 JPanel.getHeight() 获取实际坐标而不是硬编码。

    【讨论】:

    • 当我使用 JPanel.getWidth() 和 JPanel.getHeight() 我得到一个错误 Main2D.java:25: non-static method getWidth() cannot be referenced from a static context else if( x_Pos >= ( MovingBall2D.getWidth() - radius ) ) { ^ Main2D.java:33: 不能从静态上下文引用非静态方法 getHeight() else if( y_Pos >= ( MovingBall2D.getHeight() - 半径 ) ) { ^ 2 个错误
    • @Suhall Gupta:我的意思是使用小组的这些方法。在您的情况下,只需 getHeight() 和 getWidth() 就可以了。
    【解决方案3】:

    MovingBall2D.this.getHeight() 是 173(因为面板填充、标题、边框等)。这就是为什么

    只需像这样替换 if 条件:

        else if( y_Pos >= ( MovingBall2D.this.getHeight()- radius ) )
        {
            y_Pos = MovingBall2D.this.getHeight() - radius;
            speedY = -1;
        }
    

    这样做的好处是,即使用户调整了窗口大小,球也会碰到新的窗口边界。对 X 轴执行相同操作。

    【讨论】:

    • 那是因为你必须把 if 块里面的行改为: y_Pos = MovingBall2D.this.getHeight() - radius;我虽然很明显:0 无论如何我已经更新了我的答案。您现在可以删除否决票吗
    • @Suraj Chandran 是的,它有效!你能解释一下MovingBall2D.this.getHeight()我的意思是调用,你怎么调用getHeight()和getwidth()
    • 当然。 else 块在一个匿名的 actionlistener 中。所以“this”将解析为 actionlistener 实例。我们需要的是获取 MovingBall2D 对象的当前实例。当您在匿名类中时,要访问父类的实例,您执行 PARENTCLASS.this,这正是我在那里所做的。我看到你在上大学,做你 SCJP 会涵盖这些事情 :)
    • 那么你可以直接这样做。getHeight()
    • this用于引用当前类的成员,而super用于引用父类的成员
    【解决方案4】:

    尽量不要重置位置,而是使用 Tuple2D 来钳制小球的位置。我在 java 中的代码还不够多,无法真正了解正确的语法等等,但谷歌应该会有所帮助。

    【讨论】: