Java模仿Kugou,實現歌詞秀

來源:互聯網
上載者:User

可啟動並執行jar包及源碼請訪問此: http://neighborwolf.iteye.com/admin/blogs/1170037

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();}}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.