📄 lyric.java
字号:
private void init(String content) { //如果歌词的内容为空,则后面就不用执行了 //直接显示歌曲名就可以了 if (content == null || content.trim().equals("")) { list.add(new Sentence(info.getFormattedName(), Integer.MIN_VALUE, Integer.MAX_VALUE)); return; } try { BufferedReader br = new BufferedReader(new StringReader(content)); String temp = null; while ((temp = br.readLine()) != null) { parseLine(temp.trim()); } br.close(); //读进来以后就排序了 Collections.sort(list, new Comparator<Sentence>() { public int compare(Sentence o1, Sentence o2) { return (int) (o1.getFromTime() - o2.getFromTime()); } }); //处理第一句歌词的起始情况,无论怎么样,加上歌名做为第一句歌词,并把它的 //结尾为真正第一句歌词的开始 if (list.size() == 0) { list.add(new Sentence(info.getFormattedName(), 0, Integer.MAX_VALUE)); return; } else { Sentence first = list.get(0); list.add(0, new Sentence(info.getFormattedName(), 0, first.getFromTime())); } int size = list.size(); for (int i = 0; i < size; i++) { Sentence next = null; if (i + 1 < size) { next = list.get(i + 1); } Sentence now = list.get(i); if (next != null) { now.setToTime(next.getFromTime() - 1); } } //如果就是没有怎么办,那就只显示一句歌名了 if (list.size() == 1) { list.get(0).setToTime(Integer.MAX_VALUE); } else { Sentence last = list.get(list.size() - 1); last.setToTime(info == null ? Integer.MAX_VALUE : info.getLength() * 1000 + 1000); } } catch (Exception ex) { Logger.getLogger(Lyric.class.getName()).log(Level.SEVERE, null, ex); } } /** * 分析这一行的内容,根据这内容 * 以及标签的数量生成若干个Sentence对象 * @param line 这一行 */ private void parseLine(String line) { if (line.equals("")) { return; } Matcher m = Pattern.compile("(?<=\\[).*?(?=\\])").matcher(line); List<String> temp = new ArrayList<String>(); int length = 0; while (m.find()) { String s = m.group(); temp.add(s); length += (s.length() + 2); } try { String content = line.substring(length > line.length() ? line.length() : length); if (Config.getConfig().isCutBlankChars()) { content = content.trim(); } if (content.equals("")) { return; } for (String s : temp) { long t = parseTime(s); if (t != -1) { list.add(new Sentence(content, t)); } } } catch (Exception exe) { } } /** * 把如00:00.00这样的字符串转化成 * 毫秒数的时间,比如 * 01:10.34就是一分钟加上10秒再加上340毫秒 * 也就是返回70340毫秒 * @param time 字符串的时间 * @return 此时间表示的毫秒 */ private long parseTime(String time) { String[] ss = time.split("\\:|\\."); //如果 是两位以后,就非法了 if (ss.length < 2) { return -1; } else if (ss.length == 2) {//如果正好两位,就算分秒 try { int min = Integer.parseInt(ss[0]); int sec = Integer.parseInt(ss[1]); if (min < 0 || sec < 0 || sec >= 60) { throw new RuntimeException("数字不合法!"); } return (min * 60 + sec) * 1000L; } catch (Exception exe) { return -1; } } else if (ss.length == 3) {//如果正好三位,就算分秒,十毫秒 try { int min = Integer.parseInt(ss[0]); int sec = Integer.parseInt(ss[1]); int mm = Integer.parseInt(ss[2]); if (min < 0 || sec < 0 || sec >= 60 || mm < 0 || mm > 99) { throw new RuntimeException("数字不合法!"); } return (min * 60 + sec) * 1000L + mm * 10; } catch (Exception exe) { return -1; } } else {//否则也非法 return -1; } } /** * 设置其显示区域的高度 * @param height 高度 */ public void setHeight(int height) { this.height = height; } /** * 设置其显示区域的宽度 * @param width 宽度 */ public void setWidth(int width) { this.width = width; } /** * 设置时间 * @param time 时间 */ public void setTime(long time) { if (!isMoving) { tempTime = this.time = time; } } /** * 得到是否初始化完成了 * @return 是否完成 */ public boolean isInitDone() { return initDone; } private void drawKaraoke(Graphics2D gd, Sentence now, int x, int y, long t) { int nowWidth = now.getContentWidth(gd); Color gradient = null; //如果要渐入渐出才去求中间色,否则直接用高亮色画 if (Config.getConfig().isLyricShadow()) { gradient = now.getBestInColor(Config.getConfig().getLyricHilight(), Config.getConfig().getLyricForeground(), t); } else { gradient = Config.getConfig().getLyricHilight(); } if (Config.getConfig().isKaraoke()) { float f = (t - now.getFromTime()) * 1.0f / (now.getToTime() - now.getFromTime()); if (f > 0.98f) { f = 0.98f; } if (x == 0) { x = 1; } if (nowWidth == 0) { nowWidth = 1; } gd.setPaint(new LinearGradientPaint(x, y, x + nowWidth, y, new float[]{f, f + 0.01f}, new Color[]{gradient, Config.getConfig().getLyricForeground()})); } else { gd.setPaint(gradient); } Util.drawString(gd, now.getContent(), x, y); } /** * 自力更生,画出自己在水平方向的方法 * 这个做是为了更方便地把歌词显示在 * 任何想显示的地方 * @param g 画笔 */ public synchronized void drawH(Graphics g) { if (!enabled) { Sentence sen = new Sentence(info.getFormattedName()); int x = (width - sen.getContentWidth(g)) / 2; int y = (height - sen.getContentHeight(g) + Config.getConfig().getV_SPACE()) / 2; g.setColor(Config.getConfig().getLyricHilight()); Util.drawString(g, sen.getContent(), x, y); return; } //首先看是不是初始化完毕了 if (!initDone) { Sentence temp = new Sentence("正在搜索歌词"); int x = (width - temp.getContentWidth(g)) / 2; int y = (height - temp.getContentHeight(g)) / 2; g.setColor(Config.getConfig().getLyricHilight()); Util.drawString(g, temp.getContent(), x, y); return; } //如果只存在一句的话,那就不要浪费那么多计算的时候了 //直接画在中间就可以了 if (list.size() == 1) { Sentence sen = list.get(0); int x = (width - sen.getContentWidth(g)) / 2; int y = (height - sen.getContentHeight(g) + Config.getConfig().getV_SPACE()) / 2; g.setColor(Config.getConfig().getLyricHilight()); Util.drawString(g, sen.getContent(), x, y); } else { //取一个time的副本,以防止在一个方法里面产生两种time的情况 long t = tempTime; Graphics2D gd = (Graphics2D) g; int index = getNowSentenceIndex(t); if (!isMoving) { currentIndex = index; } if (index == -1) { Sentence sen = new Sentence(info.getFormattedName(), Integer.MIN_VALUE, Integer.MAX_VALUE); int x = (width - sen.getContentWidth(g) - Config.getConfig().getH_SPACE()) / 2; int y = (height - sen.getContentHeight(g) + Config.getConfig().getV_SPACE()) / 2; g.setColor(Config.getConfig().getLyricHilight()); Util.drawString(g, sen.getContent(), x, y); return; } Sentence now = list.get(index); int nowWidth = now.getContentWidth(g) + Config.getConfig().getH_SPACE(); int x = (width) / 2 - now.getHIncrease(g, t); int y = (height - now.getContentHeight(g)) / 2; this.drawKaraoke(gd, now, x, y, t); gd.setPaint(Config.getConfig().getLyricForeground()); int tempX = x; //画出中间那句之前的句子 for (int i = index - 1; i >= 0; i--) { Sentence sen = list.get(i); int wid = sen.getContentWidth(g) + Config.getConfig().getH_SPACE(); tempX = tempX - wid; if (tempX + wid < 0) { break; } if (Config.getConfig().isLyricShadow()) { if (i == index - 1) { gd.setPaint(sen.getBestOutColor(Config.getConfig().getLyricHilight(), Config.getConfig().getLyricForeground(), time)); } else { gd.setPaint(Config.getConfig().getLyricForeground()); } } Util.drawString(g, sen.getContent(), tempX, y); } gd.setPaint(Config.getConfig().getLyricForeground()); tempX = x; int tempWidth = nowWidth; //画出中间那句之后的句子 for (int i = index + 1; i < list.size(); i++) { Sentence sen = list.get(i); tempX = tempX + tempWidth; if (tempX > width) { break; } Util.drawString(g, sen.getContent(), tempX, y); tempWidth = sen.getContentWidth(g) + Config.getConfig().getH_SPACE(); } } } /** * 得到这批歌词里面,最长的那一句的长度 * @return 最长的长度 */ public int getMaxWidth(Graphics g) { int max = 0; for (Sentence sen : list) { int w = sen.getContentWidth(g); if (w > max) { max = w; } } return max; } /** * 得到一句话的X座标,因为可能对齐方式有 * 多种,针对每种对齐方式,X的座标不一 * 定一样。 * @param g 画笔 * @param sen 要求的句子 * @return 本句的X座标 */ private int getSentenceX(Graphics g, Sentence sen) { int x = 0; int i = Config.getConfig().getLyricAlignMode(); switch (i) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -