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(){
@Override
public void mouseEntered(MouseEvent e) {
closeButton.animateShow();
panel.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
}
@Override
public 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 block
e.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());
}
@Override
protected 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();
}
}
- 卡拉OK歌词秀.jar (1.1 MB)
- 描述: 直接运行即可看到效果,在Windows和Mac上都已测试,可正常运行
- 下载次数: 166
分享到:
相关推荐
【标签】"模仿酷狗7(Kugou7)界面——Java版"再次强调了项目的核心目标,即用Java来实现酷狗7的界面复刻。标签通常用于分类和搜索,帮助其他对类似项目感兴趣的人找到这个资源。 【压缩包子文件的文件列表】: 1. **...
【标题】"模仿酷狗7(Kugou7)界面V0.2——Java版"是一个项目,旨在通过Java编程语言复刻酷狗音乐播放器Kugou7的用户界面。这个项目展示了如何使用Java来创建一个类似流行音乐应用的交互式界面,为用户提供相似的音乐...
java Kugou 很好的工具包,具体很详细的
【标题】"模仿酷狗7(Kugou7)界面源码"揭示了这个项目的核心是复制酷狗7音乐播放器的用户界面设计。酷狗7是一款知名的数字音乐服务软件,以其简洁的操作界面和丰富的音乐资源受到用户的喜爱。该源码的目的在于让...
VC模仿酷狗7(Kugou7) UI界面源码,有动画效果,原创作者:邓学彬(泪闯天涯) 源码说明:内含VC++源码、易语言源码各一份.包含所有图片源码(使用Fireworks编辑) 开发环境:VC版--VS2005、Gdiplus;易语言版--...
VB 制作仿KUGOU播放器 桌面歌词效果 VB制作仿KUGOU播放器桌面歌词效果,可能这种效果很多朋友都见到过,就是把播放某首音乐的歌词显示在桌面上,其实不是桌面,是显示在屏幕下方,不过歌词字体很大,而且经过了修饰...
VC 仿酷狗音乐桌面歌词效果源码 仿QQ音乐等播放器的桌面上显示歌词效果,不过这个...演示如何制作桌面歌词秀 2.未实现卡拉OK的进度效果,本源码中仅是改变文字颜色颜色,修改下就能做到。 3.在XP VC6.0上调试通过
本项目“C#实现歌词显示.LRC歌词”是利用C#语言开发的一个功能,它允许用户在应用程序中实时显示歌曲的LRC格式歌词,类似于知名的音乐播放器酷狗(KUGOU)的功能。 LRC歌词是一种特殊的文本格式,主要用于存储带有...
【标题】:“用Java做一个管理Kugou下载的歌的小工具” 这个项目是关于使用Java编程语言开发一个小型应用程序,它的主要功能是管理和处理从酷狗音乐平台下载的歌曲。酷狗音乐是中国知名的数字音乐服务提供商,提供...
酷狗安装程序kugou8395.exe酷狗安装程序kugou8395.exe酷狗安装程序kugou8395.exe酷狗安装程序kugou8395.exe酷狗安装程序kugou8395.exe
【Kugou7界面】是基于用户界面设计的一款模仿酷狗音乐7版本的软件界面,以其独特的美感和用户体验而受到用户的喜爱。这个界面设计注重细节,力求在视觉效果和功能性之间找到平衡,为用户提供一个既美观又易于操作的...
VC模仿酷狗7(Kugou7) UI界面源码,有动画效果,原创作者:邓学彬(泪闯天涯) 源码说明:内含VC 源码、易语言源码各一份.包含所有图片源码(使用Fireworks编辑) 开发环境:VC版--VS2005、Gdiplus;易语言版--易语言5,...
8. **文本处理**:Kugou的界面可能包含歌词显示功能,这就需要处理Unicode字符集和文本渲染。Qt等库提供了方便的文本处理工具。 9. **版本控制**:"80编程社区宣言"和"80句话实现所有编程梦想.txt"可能是关于编程...
本文将深入探讨如何使用Win32 API来实现一个模仿酷狗和QQ风格的带有广告的进度条。这个过程涉及到窗口创建、消息处理、绘图以及动态更新等多个知识点。 首先,我们需要理解进度条的基本结构。在Win32中,我们可以...
Kugou-Control 是酷狗控制工具。 标签:Kugou
综合以上信息,这个项目可能是C#开发者通过深入分析酷狗音乐的特效实现,以学习和模仿为目标的案例。开发者可以通过解析源代码,了解如何使用C#来实现动态界面效果,包括但不限于使用控件动画、图形渲染技术、事件...
2. **API调用**:酷狗音乐的API被用来获取歌曲信息、播放列表、歌词等数据,这通常涉及异步请求处理,可以使用axios或fetch等库来实现。 3. **状态管理**:可能采用了Vuex来集中管理应用的状态,如当前播放的歌曲、...
【标题】"kugou.zip_kugou_音乐盒" 指的是一个与酷狗音乐盒相关的压缩文件,其中可能包含酷狗音乐播放软件的界面样式资源和代码,用于实现独特的窗口效果,如窗口之间的无缝连接。 【描述】中的“酷狗音乐盒的窗口...