多线程的学习如今做出了成果,便展示给大家
首先我们看一下效果图吧
小球运动,背景可以替换自己喜欢的图片,还有背景音乐,小球用图片来替换都很有趣!
听起来是不是有点花里胡哨,不过都只是看个人兴趣,选择自己喜欢的就是最好的。
再来看一下效果的实现
多线程是指多个线程并发执行的技术。
我们这里利用的是建立一个小球即为建立一个线程,然后多个线程共同执行便可以呈现共同的效果。
在代码编写过程中可能会遇到的问题与解决办法
-
图片与小球同时出现时有闪动现象
解决办法:采用双缓冲技术,将图片与小球先画在缓冲画布上,然后再在画布上画出 -
按钮被涂抹掉
解决办法:调整图片的位置和小球的运动位置,使其不会涂抹在画布上 -
传值问题
这个点是我经常的错误,不易发现,大家可以检查一下自己是否也犯了这样的错误,一定要确定好自己每一步的传值
这里的代码在运行的时候,小球的颜色会发生变化,很有趣,因为颜色是随机数决定的,所以会产生这种现象
代码的编写用了四个类
一 窗体类
二 监听器类
三 小球类
四 音乐类
窗体类
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
public class BallUI extends JFrame {
// 画笔
Graphics g;
// 获取缓冲图片
BufferedImage buffimage = new BufferedImage(900, 900, BufferedImage.TYPE_INT_ARGB);
// 从缓冲图片上获取画笔
Graphics buffg = buffimage.getGraphics();
public static void main(String[] args){
BallUI ball = new BallUI();
ball.showUI();
}
public void showUI() {
this.setTitle("Ball");
this.setSize(900, 900);
// setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// this.setResizable(false);
// this.setDefaultCloseOperation(3);
//设置背景颜色
// this.getContentPane().setBackground(new Color(200,255,255));
this.setLayout(new FlowLayout());
this.setLocationRelativeTo(null);
JButton add = new JButton("创建");
JButton start = new JButton("启动");
JButton stop = new JButton("停止");
JButton play = new JButton("播放音乐");
this.add(add);
this.add(start);
this.add(stop);
this.add(play);
Ballistener blis = new Ballistener(this);
blis.g = g;
add.addActionListener(blis);
start.addActionListener(blis);
stop.addActionListener(blis);
play.addActionListener(blis);
add.setFocusable(false);
start.setFocusable(false);
stop.setFocusable(false);
play.setFocusable(false);
this.addMouseListener(blis);
this.setVisible(true);
g = this.getGraphics();
Image image = new ImageIcon("bj1.jpg").getImage();
buffg.drawImage(image, 0, 40, null);
// 画笔绘制缓冲图片
g.drawImage(buffimage, 0, 40, null);
}
}
监听器类
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Random;
public class Ballistener extends MouseAdapter implements ActionListener {
BallUI bu;
int x,y;
MyArrayList<BallThread> al = new MyArrayList<BallThread>();
public Ballistener(BallUI bu) {
this.bu = bu;
}
private Random r = new Random();
public Graphics g;
public void actionPerformed(ActionEvent e) {
String str = e.getActionCommand();
Music music = new Music("C:\\Users\\89655\\Desktop\\月夜 - 双笙.mp3");
if(str.equals("创建")){
BallThread ball = new BallThread(r.nextInt(900),
r.nextInt(900),20,4,4,bu,al);
al.add(ball);
ball.start();
}else if(str.equals("启动")){
for(int i=0;i<al.size();i++){
BallThread ball =al.get(i);
ball.stateFlag=false;
}
}else if(str.equals("停止")){
for(int i=0;i<al.size();i++){
BallThread ball =al.get(i);
ball.stateFlag=true;
}
}else if(str.equals("播放音乐")){
new Music("C:\\Users\\89655\\Desktop\\月夜 - 双笙.mp3").start();
}
};
}
小球类
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.ImageIcon;
public class BallThread extends Thread {
int x, y, size, movex, movey;
private Random r = new Random();
// 获取缓冲图片
BufferedImage buffimage = new BufferedImage(900, 900, BufferedImage.TYPE_INT_ARGB);
// 从缓冲图片上获取画笔
Graphics buffg = buffimage.getGraphics();
BallUI bu;
Graphics g;
boolean stateFlag = false;
boolean flag = false;
MyArrayList<BallThread> al;
BallThread ball;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
Color color = new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255));
public BallThread(int x, int y, int size, int movex, int movey, BallUI bu, MyArrayList al) {
this.x = x;
this.y = y;
this.size = size;
this.movex = movex;
this.movey = movey;
this.bu = bu;
g = this.bu.getGraphics();
this.al = al;
}
public void run() {
while (!flag) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 缓冲画笔 绘制背景图片
Image image = new ImageIcon("bj1.jpg").getImage();
buffg.drawImage(image, 0, 40, null);
// 缓冲画笔 绘制小球 移动小球
for (int i = 0; i < al.size(); i++) {
BallThread ball = al.get(i);
ball.draw(buffg);
}
if (stateFlag) {
continue;
}
// 画笔绘制缓冲图片
g.drawImage(buffimage, 0, 40, null);
}
}
public void draw(Graphics g){
// 遍历小球的数据,画出所有小球
x += movex;
y += movey;
Random random = new Random();
//颜色进行随机设置
int r = random.nextInt(256);
int gc = random.nextInt(256);
int b = random.nextInt(256);
// 这一步为选取r,g,b中的最大值,进行一系列变换使r,g,b得到的color最亮
int max = r > gc ? r : gc;
max = max > b ? max : b;
double brighter = 255.0 / max;
r = (int) (r * brighter);
gc = (int) (gc * brighter);
b = (int) (b * brighter);
color = new Color(r, gc, b);
g.setColor(color);
g.fillOval(x, y, size, size);
// Image image = new ImageIcon("guang1.png").getImage();
// g.drawImage(image, x, y, null);
bound();
collide();
}
public void bound(){
// 当碰到边界时进行反弹处理
if (x > (900 - size) && movex > 0) {
movex = -movex;
}
if (y > (850 - size) && movey > 0) {
movey = -movey;
}
if (movex < 0 && x < 2) {
movex = -movex;
}
if (movey < 0 && y < 120) {
movey = -movey;
}
}
public void collide(){
// 当小球之间进行碰撞
for (int i = 0; i < al.size(); i++) {
ball = al.get(i);
if (this == ball) {
continue;
}
int xx = Math.abs(this.x - ball.x);
int yy = Math.abs(this.y - ball.y);
int xy = (int) Math.sqrt(xx * xx + yy * yy);
int tempx = 0;
int tempy = 0;
if (xy <= (this.size / 2 + ball.size / 2)) {
tempx = this.movex;
tempy = this.movey;
this.movex = ball.movex;
this.movey = ball.movey;
ball.movex = tempx;
ball.movey = tempy;
}
}
}
}
音乐类
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.*;
public class Music extends Thread {
Player player;
String music;
public Music(String file) {
this.music = file;
}
public void run() {
try {
play();
}
catch (FileNotFoundException | JavaLayerException e)
{
e.printStackTrace();
}
}
public void play() throws FileNotFoundException, JavaLayerException {
BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(music));
player = new Player(buffer);
player.play();
}
}
在这里需要添加额外的包,否则会产生错误,这个包帮助音乐播放,如果不需要音乐也没关系
包的下载地址在下方的链接里
链接:https://pan.baidu.com/s/1GG5Lefd0VxcSgmSGCpaILQ
提取码:xp4o
在多线程的学习中,对于代码还有很多创新点,多思考,会产生意想不到的效果