明白了简单的小球运动后,再来看看小球是如何“漫步”的!----多线程的初步运用
下面是多个小球的“漫步”图:
写出这样一个效果,我们需要建立四个类:面板类,监听器类,小球类和线程类。
【在不同的类中我们编写相对应的内容,这样做,一是,可以方便我们以后的修改;二是,有助于我们自己,对整个过程有一个自己的逻辑或认知。】
面板类(ThreadUI)
public class ThreadUI {
public void ui(){
JFrame jframe = new JFrame();
jframe.setSize(1500, 900);
jframe.setLocationRelativeTo(null);
Balllistener1 bl = new Balllistener1();
jframe.addMouseListener(bl);
jframe.addMouseMotionListener(bl);
jframe.setVisible(true);
Run run = new Run(); //只能创建一个新的线程对象
bl.allball = run.allball; //小球列表赋值给监听器上的列表
run.start(); //启动线程
Graphics g = jframe.getGraphics();
//传值传参数
run.setCS(jframe,g);
bl.setC(jframe, g);
}
//主方法
public static void main(String[] args){
ThreadUI threadui = new ThreadUI();
threadui.ui();
}
}
```
监听器类(Balllistener1)
```
public class Balllistener1 implements ActionListener,MouseListener {
JFrame jframe;
Graphics graph;
int x1,y1;
ArrayList<Ball> allball ;
//传参(获取JFrame上的画图板与画布)
public void setC(JFrame jframe,Graphics graph){
this.jframe = jframe;
this.graph = graph;
}
public void actionPerformed(ActionEvent e){
}
public void mouseClicked(MouseEvent e){
}
public void mousePressed(MouseEvent e){
x1 = e.getX();
y1 = e.getY();
// 每次按下鼠标出现五个小球
for(int i=0; i<5;i++) {
Ball ba = new Ball(jframe,x1,y1,allball);
allball.add(ba);
}
}
public void mouseReleased(MouseEvent e){
}
public void mouseEntered(MouseEvent e){
}
public void mouseExited(MouseEvent e){
}
```
小球类(Ball)
public class Ball {
Random rand = new Random();
int r = rand.nextInt(255); //随机产生颜色值
int g = rand.nextInt(255);
int b = rand.nextInt(255);
int R = rand.nextInt(100); //随机产生小球的大小(R为直径大小)
int speedX = rand.nextInt(120); //随机产生速度值
int speedY = rand.nextInt(120);
int height = 900; //边界宽度
int width = 1500; //边界长度
int life = 100; // 小球生命值
int x,y; //在界面上绘制时的x,y
JFrame jframe;
ArrayList<Ball> allball;
Graphics p;
//传参(在鼠标监听器中执行)
public Ball(JFrame jframe,int x,int y,ArrayList<Ball> allball){
this.x=x;
this.y=y;
this.allball=allball;
this.jframe=jframe;
}
//绘制小球
public void drawball(Graphics graph){
Color color = new Color(r,g,b);
graph.setColor(color);
graph.fillOval(x-R, y-R, R, R);
}
//返回小球的生命值---即在画图板上运动的时间
public boolean islive(){
return life>0;
}
//返回半径大于30的小球
public boolean isR(){
return R>30;
}
//小球碰壁并改变运动方向
public void Change(){
if(y >= height){ //球碰撞的下限
speedY *=-1; //速度反向
}else if(y <=50){
speedY *=-1;
}
if(x >= width){
speedX *=-1;
}else if(x <=50){
speedX *=-1;
}
x += speedX; //改变小球横轴方向
// y -= speedY; //改变小球纵轴方向
life--; //生命减小
}
}
```
线程类(Run)
public class Run extends Thread{
Graphics g; // 画布板上的画布
int x,y;
JFrame jframe;
ArrayList<Ball> allball = new ArrayList<>(); //列表存储画的小球---列表可以随着小球的增加,列表长度增加
//缓存--把小球都先缓存在缓存图片上----可以消除界面闪烁的状况
BufferedImage buffer = new BufferedImage(1500,900, BufferedImage.TYPE_INT_ARGB);
Graphics p = buffer.getGraphics(); // 获取缓存画布
//传参(获取JFrame上得监听器与画图板)
public void setCS(JFrame jframe,Graphics g){
this.jframe = jframe;
this.g = g;
}
//小球线程
public void run(){
while(true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//清除痕迹
p.setColor(jframe.getContentPane().getBackground()); //获得界面颜色(后画的会覆盖前画的)--用于清除之前画的小球
p.fillRect(0, 0, jframe.getWidth(), jframe.getHeight());
//把画的小球存入列表
for(int i=0; i<allball.size(); i++){
Ball ball = allball.get(i);
ball.drawball(p); // 调用小球类中画球与改变方向的方法(用缓存画布画小球)
ball.Change();
if(!ball.islive()){ //小球生命值不大于0,则移除(见小球类)
allball.remove(i);
}if(!ball.isR()){ //小球大小不大于30,则移除-----(见小球类)
allball.remove(i);
}
}
g.drawImage(buffer, 0, 0, null); //用画图板上的画布,整体画出列表中的小球
}
}
}
完成以上代码,最终小球“漫步”也就实现了~
【无论看代码还是写代码的过程都可能是枯燥乏味的,但每当看到代码运行之后的结果,感觉都会是很有成就的吧~】