教你轻松制作java音乐播放器
作者:lijiao 时间:2023-09-27 11:17:11
一、音乐播放器的实现原理
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());
}
}
}
五、总的测试效果
如下
标签:java,播放器
0
投稿
猜你喜欢
Java程序部署到服务器上,接口请求下载文件失败/文件为空/文件名不对的问题
2023-05-12 15:30:00
Java使用wait和notify实现线程之间的通信
2022-07-20 16:05:02
Spring Boot用户注册验证的实现全过程记录
2023-01-03 01:58:34
Java创建线程池为什么一定要用ThreadPoolExecutor
2023-04-22 06:03:31
C# datagridview、datagrid、GridControl增加行号代码解析
2023-02-03 10:42:56
C#操作注册表的方法
2023-06-24 14:34:46
算法练习之从String.indexOf的模拟实现开始
2023-02-23 09:20:40
关于cron表达式每天整点执行一次的问题
2023-06-24 13:51:27
JAVA ArrayList详细介绍(示例)
2023-02-18 22:30:56
java 创建线程的几种方式
2023-10-29 19:40:16
Android 创建依赖库的方法(保姆级教程)
2023-03-12 03:55:51
设置Android系统永不锁屏永不休眠的方法
2021-06-28 12:01:21
c# 获取照片的经纬度和时间的示例代码
2022-03-22 18:21:54
unity将图片转换成字体的方法
2023-02-16 22:51:09
Java中lock和tryLock及lockInterruptibly的区别
2023-05-27 11:33:56
java实现简单猜数字
2022-12-31 16:20:02
unity制作瞄准镜效果
2022-04-15 23:45:10
举例说明自定义C++异常处理的实例
2022-10-25 13:45:27
详谈java 堆区、方法区和栈区
2023-11-23 18:35:22
Android仿英语流利说取词放大控件的实现方法(附demo源码下载)
2022-07-10 23:14:18