java画图板之三——用线程让多个小球在界面自动运动

在界面上,除了可以实现点击,鼠标移动等操作的监听器,还有可以自动运行的线程

线程是指令执行的最小单位,而且多个线程是共用一个进程的内存的,也就是说我们在一个程序中可以开很多个线程,不过线程开多了当然占用的内存就多

现在我们要实现的是,运行主程序,自动跳出界面,自动出现很多小球,他们的大小,位置,运动方向速度,完全是随机的,同时碰到界面边界还要反弹

这样的要求我们的第一反应往往是一个小球开一个线程,可是这种方法在小球数量很多的时候就会越来越卡,所以我们考虑只用两个线程,一个线程创建小球,将创建的小球存在队列中,一个线程让小球动起来,从队列中一个一个的获得小球

除此之外,我们还需要一个球类,包含球的属性和运动的方法,以便线程调用,还有一个窗体类,里面包含主方法

在这四个类中,包含的变量有坐标,半径,速度,画笔,窗体,列表。我们是在球类中定义坐标,半径,速度,并且运动的方法也在球类中,所以只需要球类自己包含坐标,半径,速度即可

画笔,窗体,列表都需要在窗体类中定义,并且画笔和窗体要传到球类,因为要画球的运动轨迹

画笔,窗体,列表要传到创建小球的线程中,因这里要不断的创建小球到list中,每一个小球都要保存属于他的画笔和窗体,也就是说每创一个小球,传一次画笔和窗体,这样每个小球执行的运动方法就是独特的,不受别的小球干扰的。

列表传到让小球运动的线程中,因为要取出每个小球,并循环每个的运动方法,这样小球的坐标就不断在变,就像动起来一样

此外还要注意,不要用线程调用线程,所以两个线程最好在主函数中调用

以下是源代码
窗体类

扫描二维码关注公众号,回复: 2886625 查看本文章
package com.thread;

import java.awt.FlowLayout;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.JFrame;

public class Framball extends JFrame{
    private static ArrayList <Ball> list = new ArrayList<Ball>();//新建的list一定要初始化
    private Graphics g;
    public void showUI() {

        this.setTitle("小球");
        this.setSize(1000, 600);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        // 设置布局,流式布局
        this.setLayout(new FlowLayout());
        this.setVisible(true);
         g=this.getGraphics();
    }

    public static void main(String[] args) {
        Framball fb=new Framball();
        fb.showUI();//可见才能得到画布

        drawBall db=new drawBall();
        db.setG(fb.g,fb,list);//传三个参数
        db.start();//启动线程,线程启动后,他会自动运行,并且只运行run方法,想要运行其他方法必须另外调用

        //moveBall中的list是来自drawBall中的,所以必须等db执行完才能启动moveBall
        moveBall mb=new moveBall();
        mb.setL(list);
        mb.start();//启动线程

    }

}

小球类

package com.thread;

import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;

public class Ball {
    Random rand = new Random();
    int x = rand.nextInt(1000);
    int y = rand.nextInt(600);
    int R = rand.nextInt(100);// 半径
    private int speedX = rand.nextInt(20), speedY = rand.nextInt(20);// 小球运动速度
    private int r = 1000, d = 600;// 右限,下限
    private Graphics g;
    private Framball fb;

    public void setG(Graphics g, Framball fb) {
        this.g = g;
        this.fb = fb;
    }

    public void run() {// 表示小球的运动,可反弹,必须放在while循环中才能跑起来
        g.setColor(fb.getContentPane().getBackground());//切换为背景色
        g.fillOval(x - R - speedX, y - R - speedY, R, R);//减掉R表示在坐标替换为圆心,减掉速度表示将上一个小球掩盖掉
        g.setColor(Color.black);
        g.fillOval(x - R, y - R, R, R);
        if (y >= d)//当y接触到下限时
            speedY *= -1;//速度反向
        else if (y <= 0)
            speedY *= -1;
        if (x >= r)
            speedX *= -1;
        else if (x <= 0)
            speedX *= -1;
        x += speedX;//每一次run,就移动一次速度值
        y += speedY;
        //只执行一次run方法,小球是不会动的
    }
}

创建球的线程

package com.thread;

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;

public class drawBall extends Thread{
    ArrayList <Ball> list=new ArrayList<Ball>();//注意后面的写法,写错会报空指针异常
    Graphics g;
    Framball fb;

    public void setG(Graphics g,Framball fb,ArrayList <Ball> list) {
        this.g=g;
        this.fb=fb;
        this.list=list;
    }

    public void run() {
        while(true) {
            Ball b=new Ball();//循环中不断新建一个球
            b.setG(g, fb);//每个球都设置自己的g和fb
            list.add(b);//把球放进队列中
            try{
                sleep(10);
            }catch(Exception ef) {}
            System.out.println(list.size());
            if(list.size()==10)break;//设置小球存储的个数
        }
    }
}

移动球的线程

package com.thread;
import java.util.ArrayList;

public class moveBall extends Thread{
    int i=0;
    private ArrayList<Ball> list;//=new ArrayList<Ball>();
    public void setL( ArrayList <Ball> list) {
        this.list=list;
    }
    public void run() {
        try {
            sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        while(true) {
            for(i=0;i<list.size();i++) {
                list.get(i).run();
                try{sleep(100);}
                catch(Exception ef) {};
            }
        }
    }
}

刚点开的情况

几秒钟之后的情况

猜你喜欢

转载自blog.csdn.net/qq_37465638/article/details/81195210