用Java写LRC制作器,实现音乐播放和滑块条进度同步

       最近两天,我第一次尝试用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的内容了:)

       在进阶的路上,欢迎各位大神指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值