小白求助,JPanel在窗口里显示不出来

我想写一个小球碰撞的动画程序,可是死活显示不出来>.<

小程序有3个类,小球,窗口,还有一个画画的,具体见下文

窗口

import java.awt.Color;
import java.util.Random;
import javax.swing.*;

public class Frame {

ball ball[] = new ball[10];
Random a = new Random();

public static void main(String[] args) {
    // TODO 自动生成的方法存根
    Frame frame = new Frame();
    frame.happen();
}

public void happen(){
    JFrame frame=new JFrame();//窗口属性                                                             
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    frame.setSize(800,800);
    for (int i = 0; i < ball.length; i++){//实例化10个小球             
        ball[i] = new ball(new Color(a.nextInt(255), a.nextInt(255), a.nextInt(255)), 
                a.nextInt(750), a.nextInt(750), a.nextInt(4) + 1, a.nextInt(4) + 1, 50);
    }
    paint paint = new paint(ball);//用paint类来画小球
    frame.add(paint);//paint类加到窗口中
    while(true){//我想让动画一直动下去,所以设了个无限循环
        for (int i = 0; i < ball.length; i++){ball[i].move();}
        collision();//判断小球们的间距
        paint.repaint();//小球动完后画出新位置
        try {//加延迟防止动得太快看不清
          Thread.sleep(10);
        } catch (Exception e){e.printStackTrace();}
    }
}

public void collision(){  
    double[][] distance = new double[ball.length][ball.length];  

    for (int i = 0; i < ball.length; i++){  
        for (int j = 0; j < ball.length; j++){
            distance[i][j] = Math.sqrt(Math.pow(ball[i].getX()-ball[j].getX(), 2) + Math.pow(ball[i].getY()-ball[j].getY(), 2));  
        }
    }
    for (int i = 0; i < ball.length; i++){  
        for (int j = i + 1; j < i; j++){
            if (distance[i][j] < ball[i].getR()+ball[j].getR()){ball[i].crash(ball[j]);}//小球碰撞时调用crash方法
            }
        }
    }

}


小球

import java.awt.*;

public class ball{
private int X,Y,Vx,Vy,R;
private Color color;

public ball(Color color, int x, int y, int vx, int vy, int r){
    this.color=color;
    this.X=x;
    this.Y=y;
    this.Vx=vx;
    this.Vy=vy;
    this.R=r;
}

public void move(){
        X+=Vx;
        Y+=Vy;          
        if((X<=R)||(X>=800-R)){Vx=-Vx;}
        if((Y<=R)||(Y>=800-R)){Vy=-Vy;}
        if(X<R){X=R;}
        if(X>800-R){X=800-R;}
        if(Y<R){Y=R;}
        if(Y>800-R){Y=800-R;}
}

public void crash(ball another){
    double a = Math.abs(this.X-another.X)/(this.R+another.R);
    double b = Math.sqrt(1-a*a);
    double v1 = Vx*a-Vy*b;
    double v2 = another.Vx*a-another.Vy*b;
    int m1 = R*R, m2 = another.R*another.R;
    double v3 = ((m1-m2)*v1+2*m2*v2)/(m1+m2);
    double v4 = ((m2-m1)*v2+2*m1*v1)/(m1+m2);
    this.setVx((int)(Vx*b+v3*a));
    this.setVy((int)(Vy*a+v3*b));
    another.setVx((int)(another.Vx*b+v4*a));
    another.setVy((int)(another.Vy*a+v4*b));
}

public void setVx(int i){
    Vx=i;
}

public void setVy(int i){
    Vy=i;
}

public void setX(int i){
    X=i;
}

public void setY(int i){
    Y=i;
}

public int getVx(){
    return Vx;
}

public int getVy(){
    return Vy;
}

public int getX(){
    return X;
}

public int getY(){
    return Y;
}

public int getR(){
    return R;
}

public Color getcolor(){
    return color;
}

}


画画用的类,问题也是它

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;

public class paint extends JPanel{

ball[] ball;

public paint(ball ball[]){
    this.ball = ball;
}

public void painter(Graphics g){
    g.setColor(Color.green);
    g.fillRect(0, 0, 800, 800);
    for (int i = 0; i < ball.length; i++){        
        g.setColor(ball[i].getcolor());        
        g.fillOval(ball[i].getX()-ball[i].getR(), ball[i].getY()-ball[i].getR(), 2*ball[i].getR(), 2*ball[i].getR()); 
    }
}

}


描述

程序在eclipse里运行了,只得到一个空白的窗口。我试过在语句后面加输出hello world来判断运行到哪里,结果发现frame.add(paint);的确运行了,也进到无限循环那里了,不过paint的painter()方法没有被执行。关于JPanel的这个用法我是Head first Java上看的,确实是可行的呀··· 不知为何这里就不行了

希望有高手指点一下

2个回答

我找到原因了,很简单,你的重新方法错误了。你的代码存在两个问题:
第一,就是paint这个类的类名有问题,因为它是component,它的父类方法中有一个叫paint的方法,跟你的类名重名了。重命名这个类名为MyPainter。重命名的方法,在package模式下找到这个paint类,按快捷键ctrl+shift+R,输入新类名即可。
其次,在重命名后的MyPainter类中重新paint方法

 public void paint(Graphics g) {
        g.setColor(Color.green);
        g.fillRect(0, 0, 800, 800);
        for (int i = 0; i < ball.length; i++) {
            g.setColor(ball[i].getcolor());
            g.fillOval(ball[i].getX() - ball[i].getR(), ball[i].getY() - ball[i].getR(), 2 * ball[i].getR(),
                    2 * ball[i].getR());
        }
    }

OK,结果还比较绚烂的:
图片说明

wojiushiwo945you
毕小宝 回复A_CLEVER_TIGER: 对,跟这个有关系,子类如果要重绘需要重写父类的paint或者paintComponent方法。
2 年多之前 回复
A_CLEVER_TIGER
A_CLEVER_TIGER 我尝试了下,发现可以不修改类名,把paint方法名字换成paintComponent就可以显示出来了,换成painter什么的都不行(不知道是不是因为重写了父类的paintComponent方法?);能不能讲讲JPanel和参数g画出图像的原理?
2 年多之前 回复
A_CLEVER_TIGER
A_CLEVER_TIGER 为什么类名跟父类方法重名会出问题?
2 年多之前 回复

painter(Graphics g) 把这个改成paint(Graphics g)

strutce
丵鹰 回复A_CLEVER_TIGER: painter这个你不修改你的圆点就跟你没有画出来,你试过改完后的效果吗
2 年多之前 回复
A_CLEVER_TIGER
A_CLEVER_TIGER 并没有解决问题,head first说painter(Graphics g)是不用执行(语句)的···
2 年多之前 回复
strutce
丵鹰 painter这个不是构造方法,所以不被执行
2 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问