java 实现一个桌面弹幕

 本人菜鸟一枚,最近毕设要做一个桌面弹幕的功能,于是想着能不能用swing做一个。

首先,要实现弹幕,需要一块画布,我们写一个类继承自Jframe 。而且为了不遮挡桌面的其他部分,画布的背景应该是透明。这时我们需要用到

AWTUtilities.setWindowOpaque(this, false);//this 是你的Jframe窗口  把窗口设为透明
这个函数,首先要知道这个函数java默认工程的lib里面是没有加入的,需要额外导入rt.jar包,这个包不需要下载,在你的Jdk安装目录下lib/文件夹就可以找到,找到后直接导入你的工程就行了。

然后就是要把窗口最大化

 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();//获取桌面的大小
 Rectangle bounds = new Rectangle(screenSize); 
 this.setBounds(bounds);                                          //把窗口设为桌面大小
 this.setExtendedState(Frame.MAXIMIZED_BOTH);   
弹幕的窗口应该是在桌面的最上面的,所以你还需要设置
 this.setAlwaysOnTop(true);
java默认的jframe 是带有边框的,所以要把边框禁用
 this.setUndecorated(true);
这样弹幕的背景就算是完成了,接下了就是在背景上吧弹幕画出来。
画弹幕就要重写jframe的paint方法。
 @Override  
    public void paint(Graphics gg) {  
        super.paint(gg);}

 这个方法有一个参数Graphics。Jframe每次加载一个控件是都会调用paint方法去绘制。当需要重新绘制时,调用repaint()方法。 
  

后面我们就是通过不断调用repaint方法来让弹幕动起来的。参数Graphics可以理解为画笔,画笔可以设置相关的属性

。比如setColor(Color.RED) 方法把画笔设为红色,setFont()方法设置画笔的字体。先在桌面上画上你个你想要的字符串把。

String hello="Hello" ;
int x=300,y=300;//弹幕的坐标
@Override  
    public void paint(Graphics gg) {  
        super.paint(gg); 
        gg.setColor(Color.BLUE);   //把画笔设为蓝色
        gg.setFront(new 
        Front("Dialog",Font.BOLD,40);      //设置字体和样式,大小40
        gg.drawString(hello,x,y);   //在桌面坐标300,300的地方画出 Hello字符串
    }

 结果就是这样了 
  java 实现一个桌面弹幕_第1张图片怎么让弹幕动起来呢,前面讲到,我们需要不断调用repaint方法来进行绘制,于是我们只要不断改变弹幕的坐标 
  

然后repaint,弹幕就动起来了。当然我们要在其他线程里面重新绘制。

 while(true){
         	x--;           //改变x的坐标
             try {  
                 Thread.sleep(10);// 每10ms执行一次
             } catch (InterruptedException e) {  
                 e.printStackTrace();  
             }  
             repaint();//重新绘制
         } 

这样弹幕就动起来啦。

当然弹幕可不只有一条,我们可以用一个list来管理所有的弹幕,每次往list中添加弹幕时就可以实现往屏幕添加弹幕的效果。我们还需要定义一个类DanContent来管理我们的弹幕的各种属性,颜色,大小,字体,坐标等。弹幕的高度可以用随机数控制,只要不超出屏幕就行。

这样pain函数就变为

 public void paint(Graphics gg) {  
        super.paint(gg);  
        int st=0;
        if(list.size()>maxScreenDanmuCount) st=list.size()-maxScreenDanmuCount;
        
    	for(int i=st;i
单list里面的弹幕不断变多时,有些弹幕不在屏幕中我们就不需要去绘制了。为了减小list中的遍历次数,我们可以设置一个最大值
maxScreenDanmuCount
来限制每次重新绘制的弹幕数量。

然后绘制线程可以用Timer代替Thread,

    private void paintDanmu() {
    	Timer timer=new Timer();
    	timer.schedule(new TimerTask() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
			int st=0;              //list的起始遍历位置
	        	if(list.size()>maxScreenDanmuCount) st=list.size()-maxScreenDanmuCount;
	        	for(int i=st;i
这样弹幕就完成了,

献上效果图和源代码:(代码比较乱,大佬看见了不要喷啊!记得导入rt.jar!)

java 实现一个桌面弹幕_第2张图片

弹幕类

import java.awt.Font;
import java.io.Serializable;

public class DanContent implements Serializable {  //弹幕管理类
	public static final int TextLarge=70;
	public static final int TextMedium=45;
	public static final int TextSmart=30;
	
	
	public static final int RED=0;
	public static final int BLUE=1;
	public static final int BLACK=2;
	public static final int CYAN=3;
	public static final int REDARK_GRAY=4;
	public static final int GREEN=5;
	public static final int ORANGE=6;
	public static final int WHITE=7;
	public static final int PINK=8;
	
	
	public static final int BOLD=1;
	public static final int ITALLIC=2;
	
	
	public int x=0;
	public int y=0;
	
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private int  color;
	private int size;
	private int style;
	private String text;
	private String senderId;
	private String receiverId;
	
	public String getReceiverId() {
		return receiverId;
	}
	public void setReceiverId(String receiverId) {
		this.receiverId = receiverId;
	}
	public String getSenderId() {
		return senderId;
	}
	public void setSenderId(String senderId) {
		this.senderId = senderId;
	}
	public DanContent(int color, int size, int style, String text) {
		this.color = color;
		this.size = size;
		this.style = style;
		this.text = text;
	}
	public int getColor() {
		return color;
	}
	public void setColor(int color) {
		this.color = color;
	}
	public int getSize() {
		return size;
	}
	public void setSize(int size) {
		this.size = size;
	}
	public int getStyle() {
		return style;
	}
	public void setStyle(int style) {
		this.style = style;
	}
	public String getText() {
		return text;
	}
	public void setText(String text) {
		this.text = text;
	}
	
	
}
package paint;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Semaphore;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import com.example.lsj.teachapp.POJO.DanContent;
import com.sun.awt.AWTUtilities;  
  
/** 
 * java Swing界面编程 
 * 实现简单的弹幕
 *  
 * @author lsg 
 * 
 */  
public class DanmuNew extends JFrame implements Runnable{  
  
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public static void main(String[] args) {  
    	DanmuNew danmuNew=DanmuNew.getInstance();
    	 new Thread(new Runnable() {
 			
 			@Override
 			public void run() {
 				// TODO Auto-generated method stub
 				Scanner in=new Scanner(System.in);
 				while(true) {
 					String string=in.nextLine();
 					DanContent content=new DanContent(DanContent.ORANGE, 70, DanContent.BOLD, string);
 					danmuNew.add(content);
 				}
 				
 			}
 		}).start();
    }
    
	private int windowwidth;
	private int windwoheight;
	private int spzce;
	private int speed=1;
	private int frame=200;  
	private int maxScreenDanmuCount=50;
    private void ShowDanmu(){  
       // Thread t = new Thread(this);//启动面板的动画线程  
      //  t.start();     
    	paintDanmu();
    }  
      
    public DanmuNew(){  
    	   Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
           windwoheight=(int) screenSize.getHeight();
           windowwidth=(int) screenSize.getWidth();
           spzce=speed;
           System.out.println(windwoheight+" "+windowwidth);
           
           Rectangle bounds = new Rectangle(screenSize); 
           this.setTitle("发送弹幕");
           this.setLayout(null);
           this.setBounds(bounds); 
           this.setExtendedState(Frame.MAXIMIZED_BOTH);
           
           this.setAlwaysOnTop(true);
           // 判断是否支持透明度
           this.setUndecorated(true); // 禁用或启用此窗体的修饰。只有在窗体不可显示时
           //this.setDefaultLookAndFeelDecorated(true);
           this.setDefaultCloseOperation(EXIT_ON_CLOSE);
           Image image=Toolkit.getDefaultToolkit().getImage(getClass().getClassLoader().getResource("llll.png"));
   			setIconImage(image);
   			AWTUtilities.setWindowOpaque(this, false);
           this.setVisible(true);
         
        }  
      
   
		// TODO Auto-generated constructor stub
    	
	public void add(DanContent c) {
		
		Random random=new Random();
		c.y=random.nextInt(windwoheight-150)+50;
		c.x=windowwidth;
		list.add(c);
	}
   // Queue list=new LinkedList<>();
	private   List list=new ArrayList<>();
    @Override  
    public void paint(Graphics gg) {  
        super.paint(gg);  
      //  gg.setColor(Color.red);
       // gg.setFont(new Font("Dialog", Font.BOLD,50 ));
        int st=0;
        if(list.size()>maxScreenDanmuCount) st=list.size()-maxScreenDanmuCount;
        
    	for(int i=st;imaxScreenDanmuCount) st=list.size()-maxScreenDanmuCount;
         	for(int i=st;imaxScreenDanmuCount) st=list.size()-maxScreenDanmuCount;
	        	for(int i=st;i


你可能感兴趣的:(java)