线程的综合习题(气泡的绘制)

线程的综合练习(气泡的绘制)
关于气泡的操作总共有5个:
增加气泡,让气泡同时暂停,让气泡同时开始运动,点按钮随时消失一个气泡,点气泡让点到的气泡消失。

需要考虑的方面还有气泡立体感的绘制,在链表队列中对线程进行操作。

这次把每个气泡放在了不同的画布内,可以防止出现都在一个画布内互相影响出现错误的情况。
思路有两种:
1.主函数每次把新建的画布传给按钮监听器,监听器把画布传给线程。
2.主函数每次把面板传给监听器,在监听器里创建新画布,传给线程。

气泡移动的绘制和之前的小球都一样,暂停的控制也基本一致,这里不再说了。

引入了链表队列对线程进行管理。
增加的时候动用链表队列的INSERT操作把新的线程加入队列中。
Graphics g=JP.getGraphics();
Printthread p1=new Printthread(JP,g);
BallList.add(p1);
p1.start();

随机消失时产生一个随机数,动用REMOVE操作把小球移除。终止线程,再把小球目前所在的位置擦干净。
Random rand=new Random();
int index=rand.nextInt(BallList.count);

LinkNode node=BallList.get(index);
Printthread p=(Printthread) node.data;
p.clear();
p.stop();
BallList.remove(index);


点到气泡让它消失的写法:
创建一个鼠标监听器,点击鼠标时获取坐标。遍历整个队列,把每个气泡的角落的点的坐标和鼠标点击的位置作对比。求两点间距离,把它和小球的半径对比。如果小于等于半径,则终止这个线程,删除它在链表中的位置,擦干净小球所在的位置。



public void mousePressed(MouseEvent e) {
int x=e.getX();
int y=e.getY();
node=BallList.root;
int tot=0;
while(node!=null){
Printthread p=(Printthread) node.data;
int rr=p.getr();
int xx=p.getx()+rr;
int yy=p.gety()+rr;
if(rr>=Math.abs(Math.sqrt((xx-x)*(xx-x)+(yy-y)*(yy-y)))){
p.clear();
p.stop();
BallList.remove(tot);
}
tot++;
node=node.next;
}

}



气泡立体感的绘制:
获取气泡当前颜色,当前坐标,当前半径。
先画一个圆
通过一个循环,在圆内不断改变坐标,缩小半径,变浅颜色(递增,注意不能超过255);
画完后再把颜色还原即可。



//气泡渐变
    int rr=r;
    int xx=x;
    int yy=y;
    int cc=0;
    while(xx>=x&&yy>=y&&xx<=x+r&&yy<=y+r){
    xx++;
    yy++;
    cc=cc+12;
    rr=rr-2;
    g.fillOval(xx,yy,(int)(2*rr),(int)(2*rr));
    int R=80+cc;
    if(R>255){R=255;}
    int b=(230+cc);
    if (b>255){b=255;}
    int G=(c+cc);
    if(G>255){G=255;}
    g.setColor(new Color(R,b,G));
    }
    //颜色复原
    g.setColor(new Color((80),(230),c));



源代码:
因为每个监听器都分开写了,程序比较多。关键的部分都贴了,这里就不贴了。链表也不贴了,只放主函数和线程类。附上了JAR文件。可以玩玩看。


package IR20130718;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;



public class Bubble extends JFrame{


    boolean go=true;
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
        Bubble b=new Bubble();
        b.InitGUI();
}

private void InitGUI() {
// TODO Auto-generated method stub
this.setTitle("球");
this.setSize(new Dimension(700,500));
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(3);
this.setResizable(false);

//创建队列链表
LinkList BallList=new LinkList();

//创建新的界面
JPanel JP=new JPanel();
// //设置背景
// ImageIcon pic = new ImageIcon("image/1.jpg");
// JLabel blackground = new JLabel(pic);
//     blackground.setBounds(0, 0, pic.getIconWidth(), pic.getIconHeight());//标签大小
// this.getRootPane().add(blackground, new Integer(Integer.MIN_VALUE));
// JP.setOpaque(true);
// this.getContentPane();
// this.add(blackground);

       
//创建添加按钮
JButton BU1=new JButton("添加");
this.add(JP);

//给添加按钮添加监听器
BUAction l=new BUAction(JP,BallList);
BU1.addActionListener(l);
JP.add(BU1);

//创建暂停按钮
JButton BU2=new JButton("暂停");
BUAction2 l2=new BUAction2(JP,BallList);
BU2.addActionListener(l2);
JP.add(BU2);

//创建开始按钮
JButton BU3=new JButton("开始");
BUAction3 l3=new BUAction3(JP,BallList);
BU3.addActionListener(l3);
JP.add(BU3);

//创建随机消失按钮
JButton BU4=new JButton("随机消失");
BUAction4 l4=new BUAction4(JP,BallList);
BU4.addActionListener(l4);
JP.add(BU4);

       
       
//创建鼠标监听器
MouseListener l5=new Mouselistener1(JP,BallList);
JP.addMouseListener(l5);




       


this.setVisible(true);

}

}


线程类:


package IR20130718;

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

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Printthread extends Thread{
//控制线程进行的布尔值
boolean B=true;
//边界常量
public static final int EDGEX=700;
public static final int EDGEY=480;
//方向常量
public static final int RIGHT=1;
public static final int LEFT=2;
public static final int UP=3;
public static final int DOWN=4;
//半径
int r;
//速度
int xspeed,yspeed;
//方向
int xdirection=RIGHT,ydirection=DOWN;
//坐标
int x,y,lastx,lasty;
//保存颜色
int c;

private Graphics g;
private JPanel JP;
    public Printthread(JPanel JP,Graphics g){
    this.g=g;
        this.JP=JP;
    }
public void run(){
ImageIcon pic = new ImageIcon("image/2.jpg");
JLabel blackground = new JLabel(pic);
    blackground.setBounds(0, 0, pic.getIconWidth(), pic.getIconHeight());//标签大小
        JP.add(blackground);
    //初始值设定
Random random=new Random();
    r=20+random.nextInt(20);
    xspeed=2+random.nextInt(10);
    yspeed=2+random.nextInt(10);
    x=20+random.nextInt(3);
    y=43+random.nextInt(3);
    c=190+random.nextInt(65);
g.setColor(new Color((200),(255),c));
draw1();
    }
//清楚操作
public void clear(){
g.clearRect(x, y, 2*r, 2*r);
}
//改变B的值,使循环终止
public void setBfalse(){
B=false;
}
//改变B的值,使循环继续
public void setBtrue(){
B=true;
}
//获取坐标X值
public int getx(){
return x;
}
//获取坐标Y值
public int gety(){
return y;
}
//获取半径R;
public int getr(){
return r;
}
//绘制圆圈
    public void draw1(){
   
    while(true){
    //暂停设置
    try{
         Thread.sleep(50);
      }catch(Exception ef){}
    //坐标计算
    if(B){
    if(xdirection==RIGHT){
    x+=xspeed;
    }else{
    x-=xspeed;
    }
    if(ydirection==DOWN){
    y+=yspeed;
    }else
    {
    y-=yspeed;
    }
    //清除上次图象,画图,记录上次的坐标
    g.clearRect(lastx, lasty, 2*r, 2*r);
    g.fillOval(x,y,(int)(2*r),(int)(2*r));
    lastx=x;
    lasty=y;
    //气泡渐变
    int rr=r;
    int xx=x;
    int yy=y;
    int cc=0;
    while(xx>=x&&yy>=y&&xx<=x+r&&yy<=y+r){
    xx++;
    yy++;
    cc=cc+12;
    rr=rr-2;
    g.fillOval(xx,yy,(int)(2*rr),(int)(2*rr));
    int R=80+cc;
    if(R>255){R=255;}
    int b=(230+cc);
    if (b>255){b=255;}
    int G=(c+cc);
    if(G>255){G=255;}
    g.setColor(new Color(R,b,G));
    }
    //颜色复原
    g.setColor(new Color((80),(230),c));
   
   
        //边界判定
    if (y<=43){
   if(ydirection==DOWN){
   ydirection=UP;
   }else{
   ydirection=DOWN;
   }
           }
    if (y>=(EDGEY-r-20)){
    if(ydirection==DOWN){
       ydirection=UP;
       }else{
       ydirection=DOWN;
       }
          }
      
    if (x<=0){
       if(xdirection==RIGHT){
       xdirection=LEFT;
       }else{
       xdirection=RIGHT;
       }       
       }
       if (x>=(EDGEX-r-20)){
       if(xdirection==RIGHT){
       xdirection=LEFT;
       }else{
       xdirection=RIGHT;
       }
        }
     
   
    }
    }
    }
}




ps:还有一个功能没实现,气泡相互碰撞出现的效果,之后再写。背景设置了但是总会被擦掉,还没想到写法。