为什么会显示很多小球?

EricHxy 2004-09-14 10:34:49
我是JAVA的初学者,请教大家一个问题。
我想在屏幕上展现一个小球的移动,在遇到窗口边界的时候反弹,但是我做的程序却显示一大堆小球,而不是一个。
请问,我如何才能让屏幕上始终只看到一个小球呢?
下面是代码:
public class FirstThreadFrame
extends JFrame {
private BallPanel bPanel = null;
public FirstThreadFrame() {
Container c = this.getContentPane();
this.bPanel = new BallPanel();
c.add(this.bPanel, BorderLayout.CENTER);
Panel btnsPanel = new Panel();
//增加一个小球的按钮
JButton btnStart = new JButton("Add Ball");
btnStart.addActionListener(new
ActionListener() {
public void actionPerformed(ActionEvent e) {
addBall();
}
}
);
btnsPanel.add(btnStart);
//显示所有小球按钮
JButton btnShowBalls = new JButton("Show Balls");
btnShowBalls.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
showBalls();
}
}
);
btnsPanel.add(btnShowBalls);
//关闭按钮
JButton btnClose = new JButton("Close");
btnClose.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
);
btnsPanel.add(btnClose);
c.add(btnsPanel, BorderLayout.SOUTH);
}

private void addBall() {
try {
Random r = new Random();
int x = Math.abs(r.nextInt())/this.bPanel.getWidth();
int y = Math.abs(r.nextInt())/this.bPanel.getHeight();
Ball b = new Ball(x,y, this.bPanel.getWidth(), this.bPanel.getHeight());
//在画布上增加一个小球
this.bPanel.addBall(b);
}
catch (Exception ex) {
ex.printStackTrace();
}
}

private void showBalls() {
//创建一个线程,显示所有小球的位置变化
Thread th = new BallShowThread(this.bPanel);
th.start();
}

public static void main(String[] args) {
FirstThreadFrame fm = new FirstThreadFrame();
fm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fm.setSize(300, 400);
fm.setLocation(200, 100);
fm.setTitle("Bounce");
fm.show();
}
}
...全文
357 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
EricHxy 2004-09-17
  • 打赏
  • 举报
回复
谢谢各位,结帐咯
EricHxy 2004-09-16
  • 打赏
  • 举报
回复
但是,运行起来,确实有问题。
请高手指点原理,为什么alickma(零缺点)的办法可行。
bluesky35 2004-09-16
  • 打赏
  • 举报
回复
看下来觉得没有什么问题啊,在重画之前清楚一下试试.
alickma 2004-09-16
  • 打赏
  • 举报
回复
这个我也不太清楚,但是上面两个说的用clearRect应该是可以的,待会有时间我试一下
EricHxy 2004-09-16
  • 打赏
  • 举报
回复
非常感谢 alickma(零缺点)的回复,实践证明你的做法是正确的。
但是,我想不明白为什么。

bovy 2004-09-16
  • 打赏
  • 举报
回复
你的代码有问题!

class Ball {

//-----记录小球的原始位置--------
private int xOld = 0;
private int yOld = 0;

private int x = 0;
private int y = 0;
private int xBound = 400;
private int yBound = 400;
public final int XSIZE = 10; //球宽度
public final int YSIZE = 10; //球高度
public int dx = 10;//横向位移距离
public int dy = 10; //纵向位移距离
public Ball(int x, int y, int xBound, int yBound) {
this.x = x;
this.y = y;
this.xBound = xBound;
this.yBound = yBound;
}
public void move() {
//--记录小球的原始位置----
xOld = x;
yOld = y;

x += dx;
y += dy;
if (x < 0) {
x = 0;
dx = -dx;
}
if (x + XSIZE >= xBound) {
x = xBound - XSIZE;
dx = -dx;
}
if (y < 0) {
y = 0;
dy = -dy;
}
if (y + YSIZE >= yBound) {
y = yBound - YSIZE;
dy = -dy;
}
}

public void draw(Graphics2D g2) {
// 擦除原来位置上的小球
g2.setXORMode(g2.getBackground());
g2.fill(new Ellipse2D.Double(xOld, yOld, XSIZE, YSIZE));

// 重画新位置的小球
g2.fill(new Ellipse2D.Double(x, y, XSIZE, YSIZE));
}
}
这个用这个 class Ball 替换你的 原来的Ball。这段代码还有问题,主要是 xOld,yOld
记录的值,有时候不是小球的上一此出现的坐标,你调试调试,原理就是这样的。
alickma 2004-09-16
  • 打赏
  • 举报
回复
我也想知道原因,而且一直以来就觉得repaint这个东西怪怪的,必须实践才知道是什么效果,而且一般与想象的有区别
wandou999 2004-09-14
  • 打赏
  • 举报
回复
x.clearRect(int,int ,int,int);擦掉轨迹
alickma 2004-09-14
  • 打赏
  • 举报
回复
我又把刚才加的repaint去掉, 把moveBalls中的repaint去掉改为c.repaint(),当然这时候要把Container c = this.getContentPane();放到上一层括号中去,并把class ball作为public class的内部类。 也可以达到要求的效果。 所以证明你需要repaint的是c而不是bPanel
alickma 2004-09-14
  • 打赏
  • 举报
回复
继续实验了一下,关键问题在你要repaint的是container c,而不是bPanel
qukmei 2004-09-14
  • 打赏
  • 举报
回复
这个分接定了,哈,谢谢楼主!
alickma 2004-09-14
  • 打赏
  • 举报
回复
public void run(){
try {
for(int i=0;i<1000;i++){
this.bPanel.moveBalls();
repaint();------------------------------加上这句
Thread.sleep(5);
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}

能达到你要的效果,每次移动球时要去掉以前的球的轨迹
redlaputa 2004-09-14
  • 打赏
  • 举报
回复
public void moveBalls() {
if(balls.size()==0)
return ;
for (int i = 0; i < balls.size(); i++) {
//for (int i = 0; i < 1; i++) {
Ball b = (Ball) balls.get(i);
b.move();
}
//updateUI();
//paint();
repaint();
}

public void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D g2 = (Graphics2D) g;
System.out.println("size is :" + balls.size());
for (int i = 0; i < balls.size(); i++) {
Ball b = (Ball) balls.get(i);
b.draw(g2);
}
}

目前肯定这段代码有问题
redlaputa 2004-09-14
  • 打赏
  • 举报
回复
看了半天,头大
我觉得你应该在
repaint();
前面将前面的小球清除掉

现在的结果是这个小球的运行痕迹
EricHxy 2004-09-14
  • 打赏
  • 举报
回复
先谢谢大家了。
EricHxy 2004-09-14
  • 打赏
  • 举报
回复
class BallPanel
extends JPanel {
private ArrayList balls ;
public BallPanel(){
this.balls = new ArrayList();
this.setFocusable(true);
this.addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent event){
moveBalls();
}
}
);
}
public void addBall(Ball b) {
this.balls.add(b);
}

public void moveBalls() {
if(balls.size()==0)
return ;
for (int i = 0; i < balls.size(); i++) {
Ball b = (Ball) balls.get(i);
b.move();
}
repaint();
}

public void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D g2 = (Graphics2D) g;
System.out.println("size is :" + balls.size());
for (int i = 0; i < balls.size(); i++) {
Ball b = (Ball) balls.get(i);
b.draw(g2);
}
}
}

class Ball {
private int x = 0;
private int y = 0;
private int xBound = 400;
private int yBound = 400;
public final int XSIZE = 10; //球宽度
public final int YSIZE = 10; //球高度
public int dx = 10;//横向位移距离
public int dy = 10; //纵向位移距离
public Ball(int x, int y, int xBound, int yBound) {
this.x = x;
this.y = y;
this.xBound = xBound;
this.yBound = yBound;
}
public void move() {
x += dx;
y += dy;
if (x < 0) {
x = 0;
dx = -dx;
}
if (x + XSIZE >= xBound) {
x = xBound - XSIZE;
dx = -dx;
}
if (y < 0) {
y = 0;
dy = -dy;
}
if (y + YSIZE >= yBound) {
y = yBound - YSIZE;
dy = -dy;
}
}

public void draw(Graphics2D g2) {
g2.fill(new Ellipse2D.Double(x, y, XSIZE, YSIZE));
}
}

class BallShowThread extends Thread{
private BallPanel bPanel;
public BallShowThread(BallPanel bPanel){
this.bPanel = bPanel;
}
public void run(){
try {
for(int i=0;i<1000;i++){
this.bPanel.moveBalls();
Thread.sleep(5);
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
nwpulipeng 2004-09-14
  • 打赏
  • 举报
回复
不错,你只画了但是没有搽掉,当然有很多了

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧