java编写的音乐播放器


一、音乐播放器的实现原理

 Javase的多媒体功能很弱,所以有一个专门处理多媒体的插件叫JMF,JMF提供的模型可大致分为七类

* 数据源(Data source)
* 截取设备(Capture Device,包括视频和音频截取设备)
* 播放器(Player)
* 处理器(Processor)
* 数据池(DataSink)
* 数据格式(Format)
* 管理器(Manager)
而我所做的这个音乐播放器MyMusicPlayer(这是我创建的类名)正是调用了JMF中的Player类来实现其播放等各种功能.

我们首先要做的就是要安装JMF。JMF的安装,相信对于许多的新手来说是很伤脑筋的,JMF只支持32位的JDK版本,然而像eclipse这样的IDE环境要与JDK对应,也就是IDE环境要支持32位JDK版本。当安装完JMF之后,有时候对于MP3的播放并不成功,还需要装JMF的mp3plugin。

二、界面效果图

这里写图片描述

三、功能结构图
这里写图片描述

四、各种实现功能的代码

public class MyMusicPlayer implements ActionListener, ControllerListener,Runnable{


    JFrame j=new JFrame("音乐播放器");
    JLabel TablePlaer=new JLabel("播放列表");
    JButton BAdd=new JButton("添加歌曲");
    JButton BDelect=new JButton("删除歌曲");
    JButton BDelectTable=new JButton("清空列表");

    JButton BMoveNext=new JButton("下一曲");
    JButton BMovePrevious=new JButton("上一曲");
    JButton BPlayer=new JButton("暂停");
    JButton BStop=new JButton("停止");
    JButton BSet=new JButton("显示歌词");
    JButton BEnd=new JButton("停止");
    String[] s={"顺序播放","单曲循环","随机播放"};                             //下拉列表选项数组
    JComboBox select=new JComboBox(s);                                      //创建下拉选项
    JPanel p1=new JPanel();                                           //播放列表区域
    JPanel p=new JPanel(); 
    JPanel p2=new JPanel();                                           //按钮区域
    JPanel p3=new JPanel();  
    JLabel l=new JLabel(); 
    JPanel p5=new JPanel();    //放置播放列表
    JPanel p6=new JPanel();    //放置播放歌曲的名称

    static JPanel pp=new JPanel();
    static JLabel lb;
    public static JTextArea jt=new JTextArea();



    static int index;        //播放列表的下标
    int count;
    int flag;         //标记是随机播放还是顺序播放
    int countSecond;  //获取音乐的总时间值
    static int newtime = 0;
    int ischanging = 0;  //当鼠标是对游标进行点击,进度值也会改变
    int ispressing = 0;   //判断鼠标是否对游标进行点击
    File MusicName = null;
    static java.util.List<File> MusicNames = null;      //运用泛型,创建File对象
    File currentDirectory = null;
    List list;// 文件列表
    FileDialog open;  // 定义文件对话框对象

    Random rand = new Random(); 

    String filename;


    //进度条
    JButton timeInformation = new JButton();
    JSlider timeSlider = new JSlider(SwingConstants.HORIZONTAL, 0, 100, 0);   //(SwingConstants.HORIZONTAL)用于定向进度条为水平方向的常量的集合
                                                                                   //( 0, 100, 0)用指定的最小值、最大值和初始值创建一个水平滑块。


    // 播放
    Player player = null;    
    MusicFileChooser fileChooser = new MusicFileChooser();


    static JTextPane tp=new JTextPane();      //显示歌词区域
    static JTextArea are=new JTextArea(); //显示图片区域

    public  MyMusicPlayer(){
        j.setSize(1200, 700);
        j.setLayout(null);
        j.getContentPane().setBackground(Color.BLACK);
        j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        p.setBounds(2, 563, 1180, 95);
        p.setLayout(new BorderLayout());

        p1.setBounds(2, 3, 298, 30);           
        p1.setBackground(new Color(255,255,255));

        p2.setLayout(new GridLayout(2,3,20,20));
        p2.setBackground(Color.LIGHT_GRAY);

        p3.setLayout(new GridLayout(2,0,200,10));
        p3.setBackground(new Color(255,255,255));

        p5.setBounds(2, 35, 298, 526);
        p5.setLayout(null);
        p5.setBackground(new Color(255,255,255));

        p6.setBounds(301, 3,880, 30);
        p6.setLayout(null);
        p6.setBackground(new Color(255,255,255));




        l.setBounds(250, 4, 600, 30);     //设置显示播放的歌曲
        p6.add(l);

        /*实现图片插入
         * */
        ImageIcon ic=new ImageIcon("image\\2.3.jpg");
        ic=new ImageIcon(ic.getImage().getScaledInstance(880, 477, 2)); //获取图片以及设置图片大小

        lb=new JLabel(ic);
        lb.setOpaque(false);         
        pp.setOpaque(false);       //设置为透明

        pp.setBounds(241, 80,990, 500);


        are.setBounds(241, 56,990, 520);
        are.setOpaque(false);

        tp.setBackground(new Color(255,255,255));
        tp.setBounds(301, 35,880, 49);


        pp.add(are);
        pp.add(lb);

        // 文件列表
        list = new List(10);
        list.setBounds(100, 55, 187, 495);   //列表区域
        list.addActionListener(this);
        j.add(list);
        j.add(jt);
        j.add(tp);

        BAdd.setBounds(5,20, 90,30);
        BAdd.setBackground(new Color(255,255,255));
        BDelect.setBounds(5, 80, 90, 30);
        BDelect.setBackground(new Color(255,255,255));
        BDelectTable.setBounds(5, 140, 90, 30);
        BDelectTable.setBackground(new Color(255,255,255));
        TablePlaer.setBounds(30, 100, 200, 50);
        TablePlaer.setFont(new Font("宋体",1, 20));

        p1.add(TablePlaer);
        BMovePrevious.setBackground(new Color(255,255,255));
        BPlayer.setBackground(new Color(255,255,255));
        BMoveNext.setBackground(new Color(255,255,255));
        BStop.setBackground(new Color(255,255,255));
        select.setBackground(new Color(255,255,255));
        BSet.setBackground(new Color(255,255,255));
        p2.add(BMovePrevious);
        p2.add(BPlayer);
        p2.add(BMoveNext);
        p2.add(BStop);
        p2.add(select);
        p2.add(BSet);
        p2.setBackground(new Color(255,255,255));

        p.add(p2,BorderLayout.WEST);
        p.add(p3,BorderLayout.CENTER);


        p5.add(p);
        p5.add(BAdd);
        p5.add(BDelect);
        p5.add(BDelectTable);


        BAdd.addActionListener(this);
        BDelect.addActionListener(this);
        BDelectTable.addActionListener(this);

        BMoveNext.addActionListener(this);
        BPlayer.addActionListener(this);
        BMovePrevious.addActionListener(this);
        BStop.addActionListener(this);
        select.addActionListener(this);
        BSet.addActionListener(this);
        timeInformation.setEnabled(false);
         /*
         * 实现进度条
         * */   

          timeSlider.setMajorTickSpacing(1);//调用此方法设置主刻度标记的间隔。传入的数字表示在每个主刻度标记之间以值衡量的距离。
          timeSlider.setPaintTicks(true);   //要绘制主刻度,setPaintTicks 必须设置为 true
          timeSlider.addChangeListener(new ChangeListener() {    //创建一个新的 ChangeListener 添加到滑块。
              public void stateChanged(ChangeEvent arg0) {
                  if (player != null && ispressing == 1) {
                      newtime = (int)((JSlider)arg0.getSource()).getValue();
                      timeInformation.setText("当前时间:"+newtime/60+":"+newtime%60+"      ||      "+" 总时间: "+countSecond/60+":"+countSecond%60);
                      ischanging = 1;
                  }
              }
          });
          timeSlider.addMouseListener(new MouseAdapter(){
              public void mousePressed(MouseEvent arg0) {
                  ispressing = 1;            //当鼠标对游标进行点击时
              }
              public void mouseReleased(MouseEvent arg0) {
                  ispressing = 0;            //当鼠标不对游标进行点击时
              }
          });
          timeInformation.setText("当前时间:00:00       ||       总时间:00:00");
          timeInformation.setBackground(new Color(255,255,255));
          p3.add(timeInformation,BorderLayout.NORTH);
          p3.add(timeSlider,BorderLayout.SOUTH);

          j.add(pp);
          j.add(p5);
          j.add(p);
          j.add(p1);
          j.add(p6);
          j.setVisible(true);
//        j.setResizable(false);
    }

    /*
     * 主函数
     * */

    public static void main(String[] args) throws IOException, InterruptedException {   //InterruptedException:当线程在活动之前或活动期间处于正在等待、休眠或占用状态且该线程被中断时,抛出该异常
        MyMusicPlayer play=new MyMusicPlayer();
        Thread timeRun = new Thread(play);
        timeRun.start(); 
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        String cmd = e.getActionCommand();                   //通过获取字符串来判断是播放还是暂停,
        String box=(String)select.getSelectedItem();           //判断播放的顺序
        if(e.getSource()==BAdd)
        {
            if (player == null) {
                if (fileChooser.showOpenDialog(j) == MusicFileChooser.APPROVE_OPTION) {
                    this.MusicName = fileChooser.getSelectedFile();
                    File cd = fileChooser.getCurrentDirectory();  //获取当前路径
                    if (cd != this.currentDirectory|| this.currentDirectory == null) {
                        FileFilter[] fileFilters = fileChooser.getChoosableFileFilters();   //FileFilter 是一个抽象类,JFileChooser 使用它过滤显示给用户的文件集合
                        File files[] = cd.listFiles();  //cd.listFiles()表示返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
                        this.MusicNames = new ArrayList<File>();
                        for (File file : files) {  //每次循环都将数组中的文件对象赋给file这个变量,然后再在循环体中对这个变量进行操作如:
                                                   //for(int i=0;i<files.length;i++){  file = files[i];……}
                            filename = file.getName().toLowerCase();           //获取所有的音乐名称
                            for (FileFilter filter : fileFilters) {
                                if (!file.isDirectory() && filter.accept(file)) {
                                    this.MusicNames.add(file);
                                     list.add(filename);
                                    filename=e.getActionCommand();
                                }
                            }
                        }
                    }
                    index = MusicNames.indexOf(MusicName);   //定义歌曲的下标
                    count = MusicNames.size();
                    PlayFile();
                }
            } else {
                player.start();
            }

        }

        if(cmd.equals("暂停")){
            BPlayer.setText("播放");
            player.stop();      
            }
        if(cmd.equals("播放")){
            BPlayer.setText("暂停");
            player.start();
        }

        if(e.getSource()==BStop){            //停止
             if (player != null) {

                    player.stop();
                    timeInformation.setText("当前时间:00:00      ||      总时间:00:00");
                    timeSlider.setValue(0);
                    player.setMediaTime(new Time(0));   //设置时间为零
        }
             }
        if(e.getSource()==BMoveNext){        //下一曲
             if (player != null) {
                 if("顺序播放".equals(box)){
                        nextMusic();
                    }
                    if("随机播放".equals(box)){
                        int index = (int) rand.nextInt(this.MusicNames.size())+1;
                         if (this.MusicNames != null && !this.MusicNames.isEmpty()) {
                                 if ( ++index == this.MusicNames.size()) {
                                        index=(int) rand.nextInt(this.MusicNames.size())+1;
                                    }
                                    player.stop();          //若点击上一曲,则将当前的歌曲停止播放,播放上一曲
                                 try {
                                        player=Manager.createRealizedPlayer(MusicNames.get(index).toURI().toURL());
                                        player.prefetch();
                                        player.setMediaTime(new Time(0.0));// 从某个时间段开始播放
                                        player.addControllerListener(this);
                                        l.setText("正在播放:"+this.MusicNames.get(index).toString());
                                        list.select(index);
                                        player.start(); 
                                        flag=1;
                                    } catch (NoPlayerException | CannotRealizeException | IOException e1) {
                                        e1.printStackTrace();
                                    }
                            }
                    }
             }
        }
        if(e.getSource()==BMovePrevious){       //上一曲
             if (player != null) {
                 if("顺序播放".equals(box)){
                     PreviousMusic();
                    }
                 if("随机播放".equals(box)){
                     int index = (int) rand.nextInt(this.MusicNames.size())+1;
                     if (this.MusicNames != null && !this.MusicNames.isEmpty()) {
                         if ( index--==(int) rand.nextInt(this.MusicNames.size())+1) {
                                index = this.MusicNames.size() - 1;
                            }
                            player.stop();              //若点击上一曲,则将当前的歌曲停止播放,播放上一曲
                         try {
                                player=Manager.createRealizedPlayer(MusicNames.get(index).toURI().toURL());
                                player.prefetch();
                                player.setMediaTime(new Time(0.0));// 从某个时间段开始播放
                                player.addControllerListener(this);
                                l.setText("正在播放:"+this.MusicNames.get(index).toString());
                                list.select(index);
                                player.start(); 
                                flag=1;
                            } catch (NoPlayerException | CannotRealizeException | IOException e1) {
                                e1.printStackTrace();
                            }
                        }
                }
                }
        }
        if(e.getSource()==BDelect){             //删除歌曲
            index =list.getSelectedIndex();
            list.remove(index);
            MusicNames.remove(this.index);
        }
        if(e.getSource()==BDelectTable){          //清空列表

            list.removeAll();
            MusicNames.removeAll(MusicNames);
            player.stop();
            player = null;
        }


        //双击列表时实现播放
        list.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                // 双击时处理
                if (e.getClickCount() == 2) {
                    if(player!=null){
                        player.stop();
                    }
                    // 播放选中的文件
                    index=list.getSelectedIndex();
                    PlayFile();
                }   
            }
        });

}

    // 因为实现了"ControllerListener"接口,本方法用于处理媒体播放器传来的事件;
    public void controllerUpdate(ControllerEvent e) {
        String box=(String)select.getSelectedItem();           //判断播放的顺序
        if (e instanceof EndOfMediaEvent) {
            player.setMediaTime(new Time(0));
            if ("单曲循环".equals(box)) {
                player.start();
            }
            if("顺序播放".equals(box)){
                nextMusic();
            }
            if("随机播放".equals(box)){
                 if (this.MusicNames != null && !this.MusicNames.isEmpty()) {
                           int index = (int) rand.nextInt(this.MusicNames.size())+1;
                            try {
                                player=Manager.createRealizedPlayer(MusicNames.get(index).toURI().toURL());
                                player.prefetch();
                                player.setMediaTime(new Time(0.0));// 从某个时间段开始播放
                                player.addControllerListener(this);
                                l.setText("正在播放:"+this.MusicNames.get(index).toString());
                                list.select(index);
                                player.start(); 
                                flag=1;
                            } catch (NoPlayerException | CannotRealizeException | IOException e1) {
                                e1.printStackTrace();
                            }
                 }
            }
        }
    }

     /**
     * 获取MP3歌曲名
     * 
     * @MP3文件路径
     * @歌曲名
     */
    public String getMusicName(String str) {
        int i;
        for (i = str.length() - 1; i > 0; i--) {
            if (str.charAt(i) == '\\')
                break;
        }
        str = str.substring(i + 1, str.length() - 4);
        return str;
    }

    /**
     * 下一首 实现函数
     */
    public void nextMusic() {
    }

    /**
     * 上一首实现函数
     */
    public void PreviousMusic() {
    }


    /**
     * 播放MP3文件主函数
     */
    public void PlayFile() {
        try {
            player = Manager.createRealizedPlayer(MusicNames.get(index).toURI().toURL());
            player.prefetch();
            player.setMediaTime(new Time(0.0));// 从某个时间段开始播放
            player.addControllerListener(this);
            l.setFont(new Font("宋体",0,20));
            l.setText("正在播放:"+this.MusicNames.get(index).toString());   //显示正在播放的歌曲
            list.select(index);
            player.start();

            Mythread11 tt=new Mythread11();
            tt.start();

        } catch (Exception e1) {    //当选到一首音乐不能播放时,对其进行处理
            dealError();
            return;
        }
        this.setFrame();
        }

    public void setFrame()
    {
        countSecond = (int)player.getDuration().getSeconds();
        timeSlider.setMaximum(countSecond);
        timeSlider.setValue(0);
        newtime = 0;
    }


private void dealError() {     
        // TODO Auto-generated method stub
    MusicNames.remove(index);
    if( --count == index )
        index = 0;
    if( count == 0)
        player = null;
    else
        PlayFile();
    }

/**
 * MP3文件筛选内部类
 */
class MusicFileChooser extends JFileChooser {
  }


/**
 * MP3文件筛选辅助内部类
 * 
 */
class MyFileFilter extends FileFilter {   //FileFilter 是一个抽象类,JFileChooser 使用它过滤显示给用户的文件集合
    String[] suffarr;
    String decription;

    public MyFileFilter() {
        super();
    }

    public MyFileFilter(String[] suffarr, String decription) {
        super();
        this.suffarr = suffarr;
        this.decription = decription;
    }

    public boolean accept(File f) {
        for (String s : suffarr) {
            if (f.getName().toUpperCase().endsWith(s)) {
                return true;
            }
        }
        return f.isDirectory();
    }

    public String getDescription() {
        return this.decription;
    }
}

/**
 * 读取显示时间进度条
 */
public void run() {
    while(true) {
        sleep();
        if(player != null) {
            if(ispressing == 0) {
                if(ischanging == 1) {
                    newtime = timeSlider.getValue();
                    player.setMediaTime(new Time(((long)newtime)*1000000000));
                    ischanging = 0;
                } else {
                    newtime = (int)player.getMediaTime().getSeconds();
                    timeSlider.setValue(newtime);
                    timeInformation.setText("当前时间:"+newtime/60+":"+newtime%60+"      ||      "+" 总时间: "+countSecond/60+":"+countSecond%60);

                }

            }
        }
    }
}

//实现歌词的线程
class Mythread11 extends Thread {   
    public void run() {
        // TODO Auto-generated method stub
        try{
            LRC lrc = ReadLRC.readLRC("Traveling Light.lrc");  
            Lyrics ls = ParseLRC.parseLRC(lrc); 
            playTest(ls);
        }catch(Exception e){

        }
    }

}
static void playTest(Lyrics ls) throws InterruptedException {
    tp.setFont(new Font("宋体",1,20));
    tp.setForeground(Color.BLUE);
    StyledDocument doc = tp.getStyledDocument();
    SimpleAttributeSet center = new SimpleAttributeSet();
    StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER);      //将歌词区中显示
    doc.setParagraphAttributes(0, doc.getLength(), center, false);
    tp.setText("艺术家:" + ls.getAr());
    tp.setText("专辑:" + ls.getAl());
    tp.setText("歌曲:" + ls.getTi());
    tp.setText("歌词制作:" + ls.getBy());
    for (Lyric l : ls.getLyrics()) {
        tp.setText( l.getTxt());
        Thread.sleep(l.getTimeSize());
    }
}

}

五、总的测试效果如下
这里写图片描述

猜你喜欢

转载自blog.csdn.net/tyg88888/article/details/52955094