首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

Java仿照Kugou,实现歌词秀

2012-10-07 
Java模仿Kugou,实现歌词秀Kugou的歌词秀如图:我模拟的效果如图所示.鼠标选中后如图:歌词秀有以下细节注意

Java模仿Kugou,实现歌词秀
Kugou的歌词秀如图:


我模拟的效果如图所示.


鼠标选中后如图:




歌词秀有以下细节注意点:
  1、没有“窗口”,直接在桌面上绘制歌词
  2、歌词文字是彩色的,且颜色渐变。已唱歌词与未唱歌词的渐变色不同。歌词、、文字有黑色边框,以便于周围背景清晰区分
  3、歌词可拖动,当鼠标移上去时会变成可拖动的形状

用Java实现,有以下技术点:
  1、透明窗口
       这个需要借助JNA来实现,通过
       System.setProperty("sun.java2d.noddraw", "true"); 
       WindowUtils.setWindowTransparent(this,true);
     使得窗口透明

2、渐变的彩色文字,使用GradientPaint填充一个BufferedImage,BufferedImage的渐变色即为歌词的渐变色。然后取得歌词的形状,
       用此BufferedImage填充即可。比较麻烦的是文字的黑色边框,这个最后想了一个办法就是分别向上下左右偏移一个像素绘制
       黑色的歌词,然后在其上绘制正常的彩色渐变歌词,这样最终的叠加相关就正好是我们需要的效果。

import java.awt.AlphaComposite;import java.awt.Color;import java.awt.Cursor;import java.awt.Font;import java.awt.FontMetrics;import java.awt.GradientPaint;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.RenderingHints;import java.awt.TexturePaint;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.awt.event.MouseMotionListener;import java.awt.font.FontRenderContext;import java.awt.font.TextLayout;import java.awt.geom.Rectangle2D;import java.awt.geom.RoundRectangle2D;import java.awt.image.BufferedImage;import java.io.File;import java.io.FileReader;import java.io.InputStreamReader;import java.io.LineNumberReader;import java.util.LinkedList;import java.util.List;import javax.swing.*;import com.sun.jna.Native;import com.sun.jna.Pointer;import com.sun.jna.examples.WindowUtils;import com.sun.jna.examples.win32.User32;import com.sun.jna.examples.win32.W32API;import com.sun.jna.ptr.IntByReference;/** * 卡拉OK歌词效果,模仿Kugou桌面上的歌词秀 * @author 李涛 * @version v1.0    2011-09-11 * * 歌词秀有以下细节注意点: * 1、没有“窗口”,直接在桌面上绘制歌词 * 2、歌词文字是彩色的,且颜色渐变。已唱歌词与未唱歌词的渐变色不同。歌词、、文字有黑色边框,以便于周围背景清晰区分 * 3、歌词可拖动,当鼠标移上去时会变成可拖动的形状 *  * 用Java实现,有以下技术点: * 1、透明窗口 *    这个需要借助JNA来实现,通过 *    System.setProperty("sun.java2d.noddraw", "true");   *    WindowUtils.setWindowTransparent(this,true); *    使得窗口透明 *  * 2、渐变的彩色文字,使用GradientPaint填充一个BufferedImage,BufferedImage的渐变色即为歌词的渐变色。然后取得歌词的形状, *    用此BufferedImage填充即可。比较麻烦的是文字的黑色边框,这个最后想了一个办法就是分别向上下左右偏移一个像素绘制 *    黑色的歌词,然后在其上绘制正常的彩色渐变歌词,这样最终的叠加相关就正好是我们需要的效果。 */public class LyncWin extends JDialog {/** *  */private static final long serialVersionUID = 1L;private JLabel infoLabel;private MyCloseButton closeButton;static List<String> msgList = new LinkedList<String>();public LyncWin(){setTitle("卡拉OK歌词Demo");                                  setBounds(300, 200, 800, 110);         final ContentPane panel = new ContentPane();this.setContentPane(panel);MyMouseListener m = new MyMouseListener(this, panel);panel.addMouseListener(m);panel.addMouseMotionListener(m);getContentPane().setLayout(null);   this.getRootPane().setOpaque(false);closeButton = new MyCloseButton(this);closeButton.setOpaque(false);closeButton.setBounds(0, 0, 18, 18);   closeButton.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {System.exit(0);}});closeButton.setVisible(false);add(closeButton);setResizable(false);this.setUndecorated(true);setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);//com.sun.awt.AWTUtilities.setWindowOpacity(this, 0.93f); //com.sun.awt.AWTUtilities.setWindowShape(this, new Ellipse2D.Double(0, 0, getWidth(),getHeight()));        this.setAlwaysOnTop(true);                initMsg();        new Timer(30, new ActionListener() {            public void actionPerformed(ActionEvent e) {                LyncWin.this.repaint();//infoLabel.setText(msgList.get(i++));            }        }).start();                panel.addMouseListener(new MouseAdapter(){  @Overridepublic void mouseEntered(MouseEvent e) {closeButton.animateShow();panel.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));}@Overridepublic void mouseExited(MouseEvent e) {closeButton.animateHide();}});                System.setProperty("sun.java2d.noddraw", "true");          WindowUtils.setWindowTransparent(this,true);                this.setVisible(true);}//private void makeWinTransparent() {//Pointer winPointer = Native.getComponentPointer(this);//        W32API.HWND hwnd = new W32API.HWND();//        hwnd.setPointer(winPointer); //        IntByReference color = new IntByReference(this.getBackground().getRGB());//        //        User32.INSTANCE.SetWindowLong(hwnd, User32.GWL_EXSTYLE, User32.INSTANCE.GetWindowLong(hwnd, User32.GWL_EXSTYLE)|User32.WS_EX_LAYERED);//        User32.INSTANCE.SetLayeredWindowAttributes(hwnd, this.getBackground().getRGB(), (byte)220, User32.LWA_COLORKEY);//        this.setVisible(false);//        this.setVisible(true);//}void initMsg(){try {LineNumberReader lnr = new LineNumberReader(new InputStreamReader(Class.class.getResourceAsStream("/Msg.ini")));while(lnr.ready()){msgList.add(lnr.readLine());}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}class ContentPane extends JPanel{private static final long serialVersionUID = 1L;int i = 0; //哪一行歌曲文字int length = 0; //本行文字的宽度String msg = null;BufferedImage bufferedImage;//已唱文字的渐变色彩private Color gradientStart = new Color(238,254,218);private Color gradientCenter = new Color(153,254,17);private Color gradientEnd = new Color(232,254,3);//未唱文字的渐变色彩private Color gradientEndU = new Color(14,104,0);private Color gradientStartU = new Color(134,242,32);public ContentPane(){setFont(new Font("黑体",Font.BOLD,40));this.setOpaque(false);this.setForeground(this.getBackground());}@Overrideprotected void paintComponent(Graphics g){if(msg ==null){msg = msgList.get(0);}Graphics2D g2 = (Graphics2D)g.create();RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING,                RenderingHints.VALUE_ANTIALIAS_ON);        hints.put(RenderingHints.KEY_INTERPOLATION,                RenderingHints.VALUE_INTERPOLATION_BILINEAR);        hints.put(RenderingHints.KEY_RENDERING,                RenderingHints.VALUE_RENDER_QUALITY);        g2.setRenderingHints(hints);        g2.setColor(new Color(0,0,0));g2.setFont(getFont());FontMetrics fm = getFontMetrics(getFont());Rectangle2D rect = fm.getStringBounds(msg, g2);if(length>rect.getWidth()){length = 0;if(i>=msgList.size()){i=0;msg = msgList.get(i++);fm = getFontMetrics(getFont());rect = fm.getStringBounds(msg, g2);}else{msg = msgList.get(++i);fm = getFontMetrics(getFont());rect = fm.getStringBounds(msg, g2);}}int x = 0;int y = 48;//当关闭按钮可见时,说明鼠标移上来了,此时绘制一个半透明的底纹,以便于用户操作(否则只有当鼠标在文字轮廓//上时才能收到鼠标事件if(closeButton.isVisible()){Graphics2D newg = (Graphics2D)g.create();newg.setColor(Color.gray);newg.setComposite(AlphaComposite.SrcOver.derive((float)(closeButton.alpha*0.5)));newg.fillRoundRect(x,y-((int)rect.getHeight()-fm.getDescent()*3),(int)rect.getWidth(),(int)rect.getHeight(),10,10);newg.dispose();}//上下左右各偏离1个像素绘制黑色歌词,经过后面的彩色歌词覆盖后,即变成文字的黑色轮廓g2.drawString(msg, x-1, y);g2.drawString(msg, x+1, y);g2.drawString(msg, x, y+1);g2.drawString(msg, x, y-1);//绘制渐变彩色歌词        createBufferedImage(fm, rect,length++);TexturePaint tp = new TexturePaint(bufferedImage, rect);FontRenderContext frc = g2.getFontRenderContext();TextLayout tl = new TextLayout(msg, getFont(), frc);        g2.setPaint(tp);                g2.translate(0, y);        g2.fill(tl.getOutline(null));        g2.translate(0, -y);        //g2.drawImage(bufferedImage, null, x, y+14);g2.dispose();}//采用渐变色绘制文字protected void createBufferedImage(FontMetrics fm, Rectangle2D rectStr,int length) {        int width = (int)rectStr.getWidth();        int height = (int)rectStr.getHeight()-fm.getDescent()*2;        bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);        //绘制已唱的文字        Graphics2D g2 = bufferedImage.createGraphics();        GradientPaint painter = new GradientPaint(0, 0, gradientStart, 0, height / 2, gradientCenter);g2.setPaint(painter);Rectangle2D rect = new Rectangle2D.Double(0, 0, length, height / 2.0);g2.fill(rect);painter = new GradientPaint(0, height / 2, gradientCenter, 0,height, gradientEnd);g2.setPaint(painter);rect = new Rectangle2D.Double(0, height / 2.0 , length,height);g2.fill(rect);painter = new GradientPaint(0, height / 2-2, gradientCenter, 0,height, gradientCenter);g2.setPaint(painter);rect = new Rectangle2D.Double(0, (height / 2.0)-2 , length, 4);g2.fill(rect);//绘制未唱的文字        painter = new GradientPaint(0, 0, gradientStartU, 0, height, gradientEndU);g2.setPaint(painter);rect = new Rectangle2D.Double(length, 0, width-length, height);g2.fill(rect);g2.dispose();   }}public static void main(String[] args){try {UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());} catch (Exception e) {e.printStackTrace();} new LyncWin();}}

,我一直想把krc解析出来(苦于不知道它的文本和时间信息怎么存储,找不到相关资料),不行的话自己设计一直文件格式也行(速度要能控制到每一个字符),可是我还没想到怎么做,能指点一下吗,谢谢。

热点排行