最近两天,我第一次尝试用Java写一个GUI程序,写了个LRC文件编辑器。简单地说,就是先导入歌,然后导入歌词(顺序可以颠倒,导入歌词可以用复制粘贴代替),然后一边播放歌曲,一边添加时间标签。然后根据你输入的歌手名、专辑名等信息自动生成标准格式的LRC文件。两个菜单中的项目快捷键已经在菜单中标明。主界面长这个样子(拿绝对定位写的,有点儿丑,不支持reSize):
最终能生成这样的文件:
只供学习交流之用,希望大家能别嫌弃我比较菜。编译代码之前别忘了去官网下载Java Media Framework(地址:Java Archive Downloads - JMF),然后把5个jar包导入到工程里才能用(至少需要SE 8的版本)。有的实在不知道怎么改的Bug已经在源代码的文档注释中写清了。如果还有其他Bug希望大家能告诉我哈~ 完整代码如下:
// Coding start here
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import javax.media.ControllerEvent;
import javax.media.ControllerListener;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.Player;
import javax.media.PrefetchCompleteEvent;
import javax.media.Time;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.text.BadLocationException;
/**
* 本作品原创,可用于编辑LRC歌词,实现了滑块条的同步,时间处理以及音频处理。
* 该程序实质是JMF框架的一个实例,用awt和Swing组件配套完成。
*
* 【BUG列表】(实在无法解决的)
* 1、保存LRC文件时,只有用户输入的名称带有“.lrc”才能判断是否与文件重名。这个问题待处理;
* 2、滑块条必须快速滑动才能使用,或许是JMF框架的缺点,或许是我的事件处理方式不当;
* 3、导入一个新的MP3时,第一次按下“Pause”按钮可能会使歌曲进度错位两秒,真是让人头疼。
* 所以制作歌词的时候还是别暂停了。如果只是想听歌的话随便。。。这个问题待处理;
* 4、控制系统音量的部分实在不会弄,不像C#那么容易,干脆直接把音量滑块条删了;
* 5、显示版权窗口的时候可能不会居中显示。
*
* 在进阶的路上,欢迎各位大神指正。
* @author 赵利昂
* @version 20180222
* @since 20180219
*/
public class lrcEditor extends JFrame
{
private JPanel contentPane;
private JSlider slider;
private String filepath = "\\standby:";
private String filename = "\\standby:";
private boolean isPlaying = false;
private boolean isPaused = false;
private boolean fileAccepted = false;
private int offsetDirection = -1; // 1表示offset为提前值(正数),0表示延后(负数),-1表示不使用offset
private int currentRow = 0; // 当前光标所在行数
private Player player;
private double audioLength; // 歌曲总长度,单位是秒,但是会有小数
private Timer t = null; // 控制滑块条的进度与歌曲同步
private JTextField artists;
private JTextField title;
private JTextField album;
private JTextField madeBy;
private JTextField offset;
/**
* 应用程序初始化
*/
public static void main(String[] args)
{
EventQueue.invokeLater(() -> {
try {
lrcEditor frame = new lrcEditor();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
} catch (Exception e) {
e.printStackTrace();
}
});
}
/**
* 新建一个画布
*/
@SuppressWarnings("unchecked")
public lrcEditor()
{
addWindowListener(new WindowAdapter()
{
@Override
public void windowClosing(WindowEvent e)
{
JOptionPane.showMessageDialog(null, "Any questions or suggestions, please contact\n"
+ "Hippo by 652961752@163.com to report.\nGood day!",
"Goodbye!", JOptionPane.INFORMATION_MESSAGE);
}
});
setResizable(false);
setTitle("HIPPO Lyrics Editor - 2018.02.22");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 1080, 715);
contentPane = new JPanel();
contentPane.setBackground(SystemColor.desktop);
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JLabel lblNewLabel = new JLabel("Additional choices");
lblNewLabel.setOpaque(true);
lblNewLabel.setBorder(new LineBorder(new Color(0, 0, 0), 2));
lblNewLabel.setBackground(Color.BLACK);
lblNewLabel.setFont(new Font("微软雅黑", Font.BOLD, 17));
lblNewLabel.setForeground(Color.CYAN);
lblNewLabel.setBounds(788, 49, 161, 27);
contentPane.add(lblNewLabel);
JLabel stateLabel = new JLabel(" Lyrics editor standby.");
stateLabel.setBorder(new LineBorder(Color.WHITE, 3));
stateLabel.setOpaque(true);
stateLabel.setForeground(Color.GREEN);
stateLabel.setBackground(Color.BLACK);
stateLabel.setFont(new Font("Calibri", Font.PLAIN, 19));
stateLabel.setBounds(4, 6, 1066, 32);
contentPane.add(stateLabel);
JLabel currentLabel = new JLabel("00:00.00");
currentLabel.setFont(new Font("Calibri", Font.PLAIN, 16));
currentLabel.setForeground(Color.YELLOW);
currentLabel.setBounds(534, 106, 76, 20);
contentPane.add(currentLabel);
JLabel lengthLabel = new JLabel("00:00.00");
lengthLabel.setForeground(Color.YELLOW);
lengthLabel.setFont(new Font("Calibri", Font.PLAIN, 16));
lengthLabel.setBounds(605, 106, 64, 20);
contentPane.add(lengthLabel);
JTextArea textArea = new JTextArea();
textArea.setFont(new Font("宋体", Font.PLAIN, 16));
textArea.setBackground(new Color(204, 255, 255));
textArea.setBounds(13, 130, 657, 519);
/*
textArea.addCaretListener(new CaretListener()
{
public void caretUpdate(CaretEvent e)
{
try {
currentRow = textArea.getLineOfOffset(e.getDot());
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
*/
contentPane.add(textArea);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setBounds(10, 130, 657, 519);
contentPane.add(scrollPane);
JMenuBar menuBar = new JMenuBar();
menuBar.setBorderPainted(false);
menuBar.setBackground(SystemColor.desktop);
menuBar.setOpaque(true);
menuBar.setForeground(new Color(0, 0, 0));
setJMenuBar(menuBar);
JMenu mnFiles = new JMenu("Files");
mnFiles.setForeground(Color.WHITE);
mnFiles.setBackground(SystemColor.desktop);
mnFiles.setFont(new Font("微软雅黑", Font.PLAIN, 16));
mnFiles.setMnemonic('F');
menuBar.add(mnFiles);
JMenuItem itemSelectAudio = new JMenuItem("Select an audio");
itemSelectAudio.setAccelerator(KeyStroke.getKeyStroke("ctrl M"));
itemSelectAudio.setForeground(Color.WHITE);
itemSelectAudio.setBackground(Color.BLACK);
itemSelectAudio.addActionListener(event ->
{
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new File("."));
chooser.removeChoosableFileFilter(chooser.getAcceptAllFileFilter());
chooser.setFileFilter(new FileNameExtensionFilter("Available audio files(*.mp3 | wav | mid)", "mp3", "wav", "mid"));
int result = chooser.showOpenDialog(null);
if(result == JFileChooser.APPROVE_OPTION)
{
filename = chooser.getSelectedFile().getName();
filepath = chooser.getSelectedFile().getAbsolutePath();
if(!new File(filepath).exists())
{
JOptionPane.showMessageDialog(this, "The file does not exist!", "Error occurred", JOptionPane.OK_OPTION);
filename = "\\standby:";
filepath = "\\standby:";
fileAccepted = false;
stateLabel.setText(" Lyrics editor standby.");
}
else if(!(filename.endsWith(".mp3") || filename.endsWith(".wav") || filename.endsWith(".mid")))
{
JOptionPane.showMessageDialog(this, "Unacceptable extension!", "Error occurred", JOptionPane.OK_OPTION);
filename = "\\standby:";
filepath = "\\standby:";
fileAccepted = false;
stateLabel.setText(" Lyrics editor standby.");
}
else
{
fileAccepted = true;
stateLabel.setText(" Ready to process: " + filename);
currentRow = 0;
}
}
if(player != null)
{
t.stop();
player.stop();
slider.setValue(0);
}
});
itemSelectAudio.setFont(new Font("微软雅黑", Font.PLAIN, 14));
mnFiles.add(itemSelectAudio);
JMenuItem itemImportLyrics = new JMenuItem("Import lyrics");
itemImportLyrics.setAccelerator(KeyStroke.getKeyStroke("ctrl I"));
itemImportLyrics.addActionListener(event ->
{
JFileChooser chooser = new JFileChooser();
String lrcFilename = "";
String lrcFilepath = "";
chooser.setCurrentDirectory(new File("."));
chooser.removeChoosableFileFilter(chooser.getAcceptAllFileFilter());
chooser.setFileFilter(new FileNameExtensionFilter("Available raw lyrics files(*.txt)", "txt"));
int result = chooser.showOpenDialog(null);
if(result == JFileChooser.APPROVE_OPTION)
{
lrcFilename = chooser.getSelectedFile().getName();
lrcFilepath = chooser.getSelectedFile().getAbsolutePath();
if(!new File(lrcFilepath).exists())
{
JOptionPane.showMessageDialog(this, "The file does not exist!", "Error occurred", JOptionPane.OK_OPTION);
stateLabel.setText(" Lyrics editor standby.");
}
else if(!(lrcFilename.endsWith(".txt")))
{
JOptionPane.showMessageDialog(this, "Unacceptable extension!", "Error occurred", JOptionPane.OK_OPTION);
stateLabel.setText(" Lyrics editor standby.");
}
else
{
try(FileReader filereader = new FileReader(new File(lrcFilepath));
BufferedReader bufferreader = new BufferedReader(filereader)) {
String newline;
while ((newline = bufferreader.readLine()) != null)
textArea.append(newline + "\r\n");
textArea.append("\r\n");
} catch(IOException e) {
e.printStackTrace();
}
stateLabel.setText(" Lyric file successfully imported: " + lrcFilename);
currentRow = 0;
}
}
});
itemImportLyrics.setBackground(Color.BLACK);
itemImportLyrics.setForeground(Color.WHITE);
itemImportLyrics.setFont(new Font("微软雅黑", Font.PLAIN, 14));
mnFiles.add(itemImportLyrics);
JMenuItem itemExportLrcFiles = new JMenuItem("Export LRC files");
itemExportLrcFiles.setAccelerator(KeyStroke.getKeyStroke("ctrl O"));
itemExportLrcFiles.addActionListener(event ->
{
JFileChooser chooser = new JFileChooser();
File saveToFile = null;
String saveToFileName = ".";
chooser.setCurrentDirectory(new File("."));
chooser.removeChoosableFileFilter(chooser.getAcceptAllFileFilter());
chooser.setFileFilter(new FileNameExtensionFilter("Standard lyrics files(*.lrc)", "lrc"));
int result = chooser.showSaveDialog(null);
if(result == JFileChooser.APPROVE_OPTION)
{
saveToFile = chooser.getSelectedFile();
saveToFileName = chooser.getName(saveToFile);
if(saveToFileName == null || saveToFileName.trim().equals("") || !isLegal(saveToFileName))
JOptionPane.showMessageDialog(null, "Illegal file name detected.", "Error occurred", JOptionPane.OK_OPTION);
else if(saveToFile.isFile())
saveToFileName = saveToFile.getName();
else
saveToFile = chooser.getCurrentDirectory();
String path = saveToFile.getPath() + File.separator + saveToFileName;
if(!saveToFileName.endsWith(".lrc")) // 判断用户输入的文件名是否包含lrc扩展名
path += ".lrc";
saveToFile = new File(path);
int i = -2;
if(saveToFile.exists())
i = JOptionPane.showConfirmDialog(null, "A namesake detected. Do you want to overwrite?",
"Error occured", JOptionPane.YES_NO_CANCEL_OPTION);
if(i == JOptionPane.YES_OPTION || !saveToFile.exists())
{
try(OutputStreamWriter hippo = new OutputStreamWriter(new FileOutputStream(saveToFile)))
{
hippo.write("[ar:" + artists.getText() + "]\r\n[ti:" + title.getText() + "]\r\n[al:" + album.getText()
+ "]\r\n[by:" + madeBy.getText() + "]\r\n");
if(offsetDirection != -1 && !offset.getText().equals("")) // 如果使用offset标签
{
hippo.write("[offset:");
if(offsetDirection == 0)
hippo.write("-");
hippo.write(offset.getText() + "]\r\n");
}
for(String line : textArea.getText().split("\n"))
hippo.write("\r\n" + line);
hippo.write("\r\n");
} catch(IOException e1) {
JOptionPane.showMessageDialog(null, "An error occurred while saving.", "Error occurred", JOptionPane.OK_OPTION);
}
}
}
});
itemExportLrcFiles.setBackground(Color.BLACK);
itemExportLrcFiles.setForeground(Color.WHITE);
itemExportLrcFiles.setFont(new Font("微软雅黑", Font.PLAIN, 14));
mnFiles.add(itemExportLrcFiles);
mnFiles.addSeparator();
JMenuItem itemExit = new JMenuItem("Exit");
itemExit.setAccelerator(KeyStroke.getKeyStroke("ctrl alt K"));
itemExit.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0); // 直接关闭,不显示常规关闭时的对话框
}
});
itemExit.setBackground(Color.BLACK);
itemExit.setForeground(new Color(255, 165, 0));
itemExit.setFont(new Font("微软雅黑", Font.PLAIN, 14));
mnFiles.add(itemExit);
JMenu mnOthers = new JMenu("Others");
mnOthers.setForeground(Color.WHITE);
mnOthers.setBackground(SystemColor.desktop);
mnOthers.setFont(new Font("微软雅黑", Font.PLAIN, 16));
mnOthers.setMnemonic('O');
menuBar.add(mnOthers);
JMenuItem mntmHelp = new JMenuItem("Help");
mntmHelp.setAccelerator(KeyStroke.getKeyStroke("ctrl H"));
mntmHelp.addActionListener(event ->
{
JOptionPane.showMessageDialog(null, "The program is designed to help produce LRC files.\n"
+ "We recommend you to tag all the lyrics without pauses.\n"
+ "You can do it without instructions. Good luck!",
"Help", JOptionPane.INFORMATION_MESSAGE);
});
mntmHelp.setBackground(Color.BLACK);
mntmHelp.setForeground(Color.WHITE);
mntmHelp.setFont(new Font("微软雅黑", Font.PLAIN, 14));
mnOthers.add(mntmHelp);
mnOthers.addSeparator();
JMenuItem itemNotice = new JMenuItem("Copyright Notice");
itemNotice.setAccelerator(KeyStroke.getKeyStroke("ctrl C"));
itemNotice.addActionListener(event ->
{
AboutDialog about = new AboutDialog(this);
about.setVisible(true);
});
itemNotice.setBackground(Color.BLACK);
itemNotice.setForeground(Color.WHITE);
itemNotice.setFont(new Font("微软雅黑", Font.PLAIN, 14));
mnOthers.add(itemNotice);
/*
* 控制“播放”按钮
*/
JButton playBtn = new JButton("Play");
playBtn.setFont(new Font("Calibri", Font.PLAIN, 18));
playBtn.addActionListener(event ->
{
if(player != null)
{
if(isPaused)
isPaused = false;
else
{
processPlayer();
setAudioPath();
}
}
else
setAudioPath();
isPlaying = true;
player.realize();
player.prefetch();
player.start();
player.addControllerListener(new ControllerListener()
{
public void controllerUpdate(ControllerEvent controllerevent)
{
if(controllerevent instanceof PrefetchCompleteEvent)
{
audioLength = player.getDuration().getSeconds();
lengthLabel.setText(getFormatLength());
}
}
});
stateLabel.setText(" Playing: " + filename);
t = new Timer(87, e ->
{
currentLabel.setText(getCurrentFormatLength());
int currentValue = (int) (player.getMediaTime().getSeconds() * 1000.0 / audioLength);
slider.setValue(currentValue);
if(slider.getValue() >= 1000)
{
stateLabel.setText(" Playing accomplished: " + filename);
currentLabel.setText("00:00.00");
t.stop();
slider.setValue(0);
}
});
t.start();
});
playBtn.setBounds(247, 44, 97, 35);
contentPane.add(playBtn);
/*
* 控制“暂停”按钮
*/
JButton pauseBtn = new JButton("Pause");
pauseBtn.addActionListener(event ->
{
if(player != null)
{
stateLabel.setText(" Paused: " + filename);
isPaused = true;
player.stop();
t.stop();
}
});
pauseBtn.setFont(new Font("Calibri", Font.PLAIN, 18));
pauseBtn.setBounds(140, 44, 97, 35);
contentPane.add(pauseBtn);
/*
* 控制“停止播放”按钮
*/
JButton stopBtn = new JButton("Stop");
stopBtn.addActionListener(event ->
{
if (player != null)
{
stateLabel.setText(" Stopped playing: " + filename);
currentLabel.setText("00:00.00");
player.stop();
player.setMediaTime(new Time(0));
t.stop();
slider.setValue(0);
}
currentRow = 0;
});
stopBtn.setFont(new Font("Calibri", Font.PLAIN, 18));
stopBtn.setBounds(33, 44, 97, 35);
contentPane.add(stopBtn);
slider = new JSlider();
slider.addMouseListener(new MouseAdapter()
{
@Override
public void mouseReleased(MouseEvent e)
{
double sliderValue = (double) slider.getValue();
double newLength = audioLength * sliderValue / 1000.0;
player.setMediaTime(new Time(newLength));
}
});
slider.setMaximum(1000);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
slider.setValue(0);
slider.setBackground(Color.BLACK);
slider.setBounds(10, 86, 657, 23);
contentPane.add(slider);
JPanel panel = new JPanel();
panel.setForeground(Color.WHITE);
panel.setBackground(Color.BLACK);
panel.setBorder(new LineBorder(new Color(192, 192, 192), 3, true));
panel.setBounds(682, 61, 379, 588);
contentPane.add(panel);
panel.setLayout(null);
madeBy = new JTextField();
madeBy.setFont(new Font("Calibri", Font.PLAIN, 14));
madeBy.setColumns(10);
madeBy.setBounds(108, 150, 249, 26);
panel.add(madeBy);
offset = new JTextField();
offset.setFont(new Font("Calibri", Font.PLAIN, 14));
offset.setText("0");
offset.setColumns(10);
offset.setBounds(108, 189, 249, 26);
panel.add(offset);
album = new JTextField();
album.setFont(new Font("Calibri", Font.PLAIN, 14));
album.setColumns(10);
album.setBounds(108, 111, 249, 26);
panel.add(album);
title = new JTextField();
title.setFont(new Font("Calibri", Font.PLAIN, 14));
title.setColumns(10);
title.setBounds(108, 72, 249, 26);
panel.add(title);
artists = new JTextField();
artists.setFont(new Font("Calibri", Font.PLAIN, 14));
artists.setBounds(108, 33, 249, 26);
panel.add(artists);
artists.setColumns(10);
JLabel lblNewLabel_1 = new JLabel("Artists: ");
lblNewLabel_1.setFont(new Font("Calibri", Font.PLAIN, 18));
lblNewLabel_1.setBounds(23, 31, 75, 30);
lblNewLabel_1.setForeground(Color.WHITE);
lblNewLabel_1.setBackground(Color.BLACK);
lblNewLabel_1.setOpaque(true);
panel.add(lblNewLabel_1);
JLabel lblTitle = new JLabel("Title: ");
lblTitle.setOpaque(true);
lblTitle.setForeground(Color.WHITE);
lblTitle.setFont(new Font("Calibri", Font.PLAIN, 18));
lblTitle.setBackground(Color.BLACK);
lblTitle.setBounds(23, 70, 75, 30);
panel.add(lblTitle);
JLabel lblAlbum = new JLabel("Album: ");
lblAlbum.setOpaque(true);
lblAlbum.setForeground(Color.WHITE);
lblAlbum.setFont(new Font("Calibri", Font.PLAIN, 18));
lblAlbum.setBackground(Color.BLACK);
lblAlbum.setBounds(23, 109, 75, 30);
panel.add(lblAlbum);
JLabel lblMadeBy = new JLabel("Made by: ");
lblMadeBy.setOpaque(true);
lblMadeBy.setForeground(Color.WHITE);
lblMadeBy.setFont(new Font("Calibri", Font.PLAIN, 18));
lblMadeBy.setBackground(Color.BLACK);
lblMadeBy.setBounds(23, 148, 75, 30);
panel.add(lblMadeBy);
JLabel lblOffset = new JLabel("Offset: ");
lblOffset.setOpaque(true);
lblOffset.setForeground(Color.WHITE);
lblOffset.setFont(new Font("Calibri", Font.PLAIN, 18));
lblOffset.setBackground(Color.BLACK);
lblOffset.setBounds(23, 187, 75, 30);
panel.add(lblOffset);
JLabel lblOffsetType = new JLabel("Offset type: ");
lblOffsetType.setOpaque(true);
lblOffsetType.setForeground(Color.WHITE);
lblOffsetType.setFont(new Font("Calibri", Font.PLAIN, 18));
lblOffsetType.setBackground(Color.BLACK);
lblOffsetType.setBounds(23, 226, 91, 30);
panel.add(lblOffsetType);
@SuppressWarnings("rawtypes")
JComboBox comboBox = new JComboBox();
comboBox.setFont(new Font("Calibri", Font.PLAIN, 14));
comboBox.addActionListener(event ->
{
String currentBox = comboBox.getSelectedItem().toString();
switch(currentBox)
{
case "Cancel offset":
offset.setEnabled(false);
offset.setText("0");
offsetDirection = -1;
break;
case "Ahead of time":
offset.setEnabled(true);
offset.setText("");
offsetDirection = 1;
break;
case "Lag of time":
offset.setEnabled(true);
offset.setText("");
offsetDirection = 0;
}
});
comboBox.setBounds(128, 228, 229, 26);
comboBox.addItem("Cancel offset");
comboBox.addItem("Ahead of time");
comboBox.addItem("Lag of time");
panel.add(comboBox);
JButton btnAddArtistsAnd = new JButton("Add artists, title and author in the front");
btnAddArtistsAnd.addActionListener(event ->
{
textArea.insert("[-00:00.10]" + artists.getText() + " - " + title.getText() + "\n[-00:00.07]\n[-00:00.04]Made by "
+ madeBy.getText() + "\n[-00:00.01]\n", 0);
});
btnAddArtistsAnd.setFont(new Font("Calibri", Font.PLAIN, 18));
btnAddArtistsAnd.setBounds(23, 272, 334, 35);
panel.add(btnAddArtistsAnd);
JButton btnAppendEndIcon = new JButton("Append an end line in the last milisecond");
btnAppendEndIcon.addActionListener(event ->
{
textArea.append("[" + getFormatLength() + "]--- This is the end of the lyric. ---\n");
});
btnAppendEndIcon.setFont(new Font("Calibri", Font.PLAIN, 18));
btnAppendEndIcon.setBounds(23, 321, 334, 35);
panel.add(btnAppendEndIcon);
JButton btnRestoreAllChoices = new JButton("Restore all choices to default settings");
btnRestoreAllChoices.addActionListener(event ->
{
int choice = JOptionPane.showConfirmDialog(null, "Start restoring?", "Confirmation required", JOptionPane.YES_NO_CANCEL_OPTION);
if(choice == JOptionPane.YES_OPTION)
{
artists.setText("");
title.setText("");
album.setText("");
madeBy.setText("");
offset.setText("0");
comboBox.setSelectedItem("Cancel offset");
offsetDirection = -1;
JOptionPane.showMessageDialog(null, "Done.", "From restore process", JOptionPane.OK_CANCEL_OPTION);
}
});
btnRestoreAllChoices.setFont(new Font("Calibri", Font.PLAIN, 18));
btnRestoreAllChoices.setBounds(23, 370, 334, 35);
panel.add(btnRestoreAllChoices);
JTextArea txtrWarningaddAnd = new JTextArea();
txtrWarningaddAnd.setFont(new Font("Calibri", Font.PLAIN, 18));
txtrWarningaddAnd.setBackground(new Color(0, 0, 0));
txtrWarningaddAnd.setEditable(false);
txtrWarningaddAnd.setForeground(new Color(255, 255, 102));
txtrWarningaddAnd.setLineWrap(true);
txtrWarningaddAnd.setText("[Warning] \"Add\" and \"Append\" buttons "
+ "should only be used after you have tagged the lyrics. \r\n"
+ "Once you started tagging, do not change the \r\nline counts of the lyric. "
+ "The usage of \"offset\" is not recommended due to compatibility.\r\n "
+ " --- Hippo");
txtrWarningaddAnd.setBounds(20, 419, 345, 160);
panel.add(txtrWarningaddAnd);
JButton addTimeBtn = new JButton("Add time tags");
addTimeBtn.addActionListener(event ->
{
String currentTimeTag = String.format("[%s]", getCurrentFormatLength());
int position = 0;
int lineCount = textArea.getLineCount();
try {
position = textArea.getLineStartOffset(currentRow++);
if(currentRow >= lineCount)
textArea.append("\n");
} catch (BadLocationException e1) {
e1.printStackTrace();
}
textArea.setCaretPosition(position);
textArea.insert(currentTimeTag, position);
});
addTimeBtn.setFont(new Font("Calibri", Font.PLAIN, 18));
addTimeBtn.setBounds(381, 44, 248, 35);
contentPane.add(addTimeBtn);
JLabel label = new JLabel("/");
label.setForeground(Color.YELLOW);
label.setFont(new Font("Calibri", Font.PLAIN, 16));
label.setBounds(595, 105, 14, 20);
contentPane.add(label);
}
/**
* 检查保存的文件名是否合法
* @param s 要被检查的字符串
* @return 是否合法的标志(true/false)
*/
public static boolean isLegal(String s)
{
if(s.contains("/") || s.contains("\\") || s.contains(":") || s.contains("\"") || s.contains("|") || s.contains("*")
|| s.contains("<") || s.contains(">") || s.contains("\'") || s.contains("?") || s.contains(";") || s.contains("="))
return false;
return true;
}
/**
* 在播放之前的预处理工作
*/
public void processPlayer()
{
if(!fileAccepted)
{
JOptionPane.showMessageDialog(this, "You haven't choosen a file!", "Error occurred", JOptionPane.OK_OPTION);
return;
}
if(isPlaying)
{
isPlaying = false;
player.stop();
player.setMediaTime(new Time(0));
}
}
/**
* 将播放路径添加至Player
*/
public void setAudioPath()
{
try {
player = Manager.createPlayer(new MediaLocator("file:" + filepath));
} catch(Exception e) {
System.out.println(e.getMessage());
}
}
/**
* 处理音乐文件总长度的标签
* @return 歌曲的总长度,格式为mm:ss.nn(n为毫秒数)
*/
public String getFormatLength()
{
StringBuilder sb = new StringBuilder();
int minutes = (int) audioLength / 60;
if(minutes < 10)
sb.append("0");
sb.append(minutes);
sb.append(":");
int seconds = (int) audioLength % 60;
if(seconds < 10)
sb.append("0");
sb.append(seconds);
sb.append(".");
sb.append(String.format("%02.0f", (audioLength - (int) audioLength) * 100.0));
return sb.toString();
}
/**
* 处理音乐文件当前位置的标签
* @return 当前音乐播放的进度,格式为mm:ss.nn(n为毫秒数)
*/
public String getCurrentFormatLength()
{
StringBuilder sb = new StringBuilder();
double currentSeconds = player.getMediaTime().getSeconds();
int minutes = (int) currentSeconds / 60;
if(minutes < 10)
sb.append("0");
sb.append(minutes);
sb.append(":");
int seconds = (int) currentSeconds % 60;
if(seconds < 10)
sb.append("0");
sb.append(seconds);
sb.append(".");
sb.append(String.format("%02.0f", (currentSeconds - (int) currentSeconds) * 100.0));
return sb.toString();
}
}
/**
* 版权声明窗口(居中显示可能会存在问题)
* @author 赵利昂
* @since 20180222
*/
class AboutDialog extends JDialog
{
public AboutDialog(JFrame owner)
{
super(owner, "Copyright Notice", true);
add(new JLabel("<html><h2><font color=\"blue\"><b><i> HIPPO</i>(C) Lyrics Editor </b></h2></color>"
+ "<p> All rights reserved.</html>"),
BorderLayout.CENTER);
JButton ok = new JButton("I got it.");
ok.addActionListener(event -> setVisible(false));
JPanel panel = new JPanel();
panel.add(ok);
add(panel, BorderLayout.SOUTH);
setLocationRelativeTo(null);
pack();
}
}
个人对Java的GUI编程不是特别感兴趣。。C#还是比较喜欢的。往后就开始学习JavaEE的内容了:)
在进阶的路上,欢迎各位大神指正。