• Java小项目——多线程弹球


    一、需求分析

    版本V1:多线程绘制小球

    版本V2:开启一个线程,绘制队列listBall内多个小球

    版本V3:使用启动和暂停按钮,控制线程小球的运动

    二、版本V1:多线程绘制小球

    点击绘制区域,获取x和y的坐标;

    创建和开始一个线程,线程中run()函数中内容为绘制小球;

    小球绘制卸载for循环内,每次加上速度v,更新坐标。

    UI页面类:

    package com.java8.threadballV1;
    
    import javax.swing.*;
    import java.awt.*;
    
    public class BallFrame {
        public static void main(String[] arg){
            BallFrame bf = new BallFrame();
            bf.showUI();
        }
    
        private void showUI() {
            JFrame jf = new JFrame();
            jf.setName("线程小球V1");
            jf.setSize(500,600);
            jf.setDefaultCloseOperation(3);
            jf.setLocationRelativeTo(null);
    
            JPanel jp_control = new JPanel();
            JPanel jp_ball = new JPanel();
            jp_control.setBackground(Color.lightGray);
            jp_ball.setBackground(Color.white);
            jf.add(jp_control,BorderLayout.NORTH);
            jf.add(jp_ball,BorderLayout.CENTER);
    
            JButton jb  = new JButton("run");
            jp_control.add(jb);
    
            jf.setVisible(true);
    
            Graphics g = jp_ball.getGraphics();
            ThreadListener threadListener = new ThreadListener(g);
            jp_ball.addMouseListener(threadListener);
            jb.addActionListener(threadListener);
    
        }
    
    }
    

    监听器类:

    点击屏幕,启动线程,thread.start(),启动重写后的run()函数

    package com.java8.threadballV1;
    
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    
    public class ThreadListener extends MouseAdapter implements ActionListener {
    
        private Graphics g;
    
        public ThreadListener(Graphics g) {
            this.g = g;
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("run");
        }
    
        @Override
        public void mouseClicked(MouseEvent e) {
            int x = e.getX();
            int y = e.getY();
            BallThread ballThread = new BallThread(g,x,y);
            ballThread.start();
        }
    }
    

    触发器类:

    重写run()函数:循环绘制小球,每次x,y分别加上v。

    package com.java8.threadballV1;
    
    import java.awt.*;
    
    public class BallThread extends Thread {
    
        private Graphics g;
        int x;
        int y;
        int v = 1;
    
        public BallThread(Graphics g,int x,int y){
            this.g = g;
            this.x = x;
            this.y = y;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 200; i++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
                x += v;
                y += v;
                g.setColor(Color.orange);
                g.fillOval(x, y, 20, 20);
            }
        }
    }
    

    二、版本V2:开启一个线程,绘制队列listBall内多个小球

    1、Ball类:增加该类别,存储小球与ArrayList<Ball> listBall内,用于在线程中绘制。

    存储了ball的属性:x和y

    包含了绘制ball的代码:考虑了撞墙的情况

    package com.java8.threadballV2;
    
    import javax.swing.*;
    import java.awt.*;
    
    public class Ball {
        private int x, y;
        private int radius = 30;
        private int vx = 3, vy = 3;
    
        public Ball(int x, int y) {
            this.x = x;
            this.y = y;
        }
    
        public void drawBall(Graphics g, JPanel jp_ball) {
            //1.判断是否为边界
            if (x <= 0 || x + radius >= jp_ball.getWidth()) {
                vx = -vx;
            }
            if (y <= 0 || y + radius >= jp_ball.getHeight()) {
                vy = -vy;
            }
            //2.绘制一个背景色小球,覆盖于上次绘制的小球上
            g.setColor(Color.white);
            g.fillOval(x, y, radius, radius);
            //3.获取本次的x和y
            x += vx;
            y += vy;
            //4.绘制本次小球
            g.setColor(Color.orange);
            g.fillOval(x, y, radius, radius);
        }
    }
    

    2、BallListener:点击时,生成ball对象,存入listBall

    构造方法中:

    若线程不存在,则创建线程,传入画笔g、画布jp_ball、队列listBall

    mouseClick中:

    每点击一次,则生成一个ball对象;

    将ball对象add如队列listBall中。

    package com.java8.threadballV2;
    
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.util.ArrayList;
    
    public class ThreadListener extends MouseAdapter implements ActionListener {
    
        private int x,y;
        //JPanel:用于获取画笔的长和宽
        private JPanel jp_ball;
        //队列:存储球的对象,不用定义初始长度
        private ArrayList<Ball> listBall = new ArrayList<Ball>();
        //线程:线程中循环绘制listBall中的所有ball
        private BallThread ballThread;
    
        public ThreadListener(Graphics g,JPanel jp_ball) {
            this.jp_ball = jp_ball;
            //构造函数只使用1次,在此处创建线程,则线程一定只有一个——实现一个线程绘制多个小球
            //创建线程对象,构造方法将画笔和画布和队列listBall传入
            if(ballThread==null){
                System.out.println("线程创建");
                ballThread = new BallThread(g,listBall,jp_ball);
                ballThread.start();
            }
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("run");
        }
    
        @Override
        public void mouseClicked(MouseEvent e) {
            // 1.获取x和y
            x = e.getX();
            y = e.getY();
            // 2.判断点击是否超出界面,超出则把其设置为边界x和y
            if (x + 20 >= jp_ball.getWidth()){
                x = jp_ball.getWidth() - 30;
            }
            if (y + 20 >= jp_ball.getHeight()){
                y = jp_ball.getHeight() - 30;
            }
            // 3.点击时,创建小球对象,
            Ball ball = new Ball(x,y);
            // 4.将小球对象存入小球队列listBall中
            listBall.add(ball);
        }
    }
    

    3、BallThread:重写的run(),循环调用listBall中ball的drawBall绘制方法

    package com.java8.threadballV2;
    
    import javax.swing.*;
    import java.awt.*;
    import java.util.ArrayList;
    
    public class BallThread extends Thread {
    
        private Graphics g;
        private JPanel jp_ball;
        private ArrayList<Ball> listBall;
    
        public BallThread(Graphics g,ArrayList<Ball> listBall,JPanel jp_ball){
            this.g = g;
            this.listBall = listBall;
            this.jp_ball = jp_ball;
        }
    
        @Override
        public void run() {
            while(true){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                for (int i=0;i<listBall.size();i++){
                    listBall.get(i).drawBall(g,jp_ball);
                }
            }
    
        }
    }
    

    4、BallFrame中:仅仅在创建监听器时,多传入jp_ball对象

            ThreadListener threadListener = new ThreadListener(g,jp_ball);
    

    结果:

  • 相关阅读:
    HDU 4389 X mod f(x)
    SRM 400(1-250pt, 1-500pt)
    FZU 2113 Jason的特殊爱好
    POJ 3208 Apocalypse Someday
    HDU 4734 F(x)
    HDU 3555 Bomb
    HDU 2089 不要62
    poj2488(A Knight's Journey)
    poj3267(The Cow Lexicon)
    poj2513(Colored Sticks)
  • 原文地址:https://www.cnblogs.com/iriswang/p/11084646.html
Copyright © 2020-2023  润新知