建立这个播放器的简单思想就是使用线程和界面同时运行,达到播放和界面按钮的功能。
做好的界面如下:
- 使用Swing包先建立好的一个大概的界面,这时候是要先想好自己要实现大概的一个播放音乐的同时还可以实现选歌曲,播放下一首的功能,还能看到音乐的播放列表。确定大概功能以后就是大概这么样的界面。但是没有功能。
- 在建立了界面以后开始查找文件,写有关查找文件的代码,这里使用到了这样两个库:
import java.io.File;
import java.util.Arrays;
- 做好界面找到文件了以后就可以书写有关于线程方面的代码。
在播放音乐的时候发生了很大的问题!
一定要用线程来解决!
为什要放线程呢??
因为我也是刚刚才学习Java 的,之前对线程也只是停留在书籍上的知识。在书写这个播放器的程序的时候我就发现,如果直接播放音乐文件的话就会导致音乐一直在后台进行播放而且当前的播放器窗口就完全没有用了,甚至连关闭都不能关闭。所以我意识到是后台运行播放音乐占用 了线程,导致当前界面不受控制。学习了一个晚上的线程以后终于能在播放音乐的同时控制窗口了。
实现播放部分的代码:
/**播放音乐的方法*/
public void play() {
try {
System.out.println("text正在尝试播放音乐"+filename+"开始播放音乐");
BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(filename));
player = new Player(buffer);
player.play();
} catch (Exception e) {
System.out.println(e);
}
}
/**让线程开始运行
* @param fouse */
public void torun(boolean fouse) { //函数内的参数时根据错误的处理办法进行自动添加的
//key = true;
if (value == null)return;
try {
if (key) {
System.out.println("已经有一个线程正在播放音乐不能再播放音乐");
return;
}
MyThread music = new MyThread();
music_2= music;
music_2.start();
key = true;
}catch (Exception a) { //这里基本上不会出错误
System.out.println("开始播放音乐错误!或并使用新建线程的方式来播放音乐");
}
}
- 建立了线程和播放程序以后可以完善更多的功能了。
- 创建暂停按钮
在这个程序中,我并没有真正的实现在暂停按钮,而是直接简单明了的使用stop命令来关闭音乐的线程
/**让线程停止并且删除*/
@SuppressWarnings("deprecation")
public void tostop() {
System.out.println("开始处理暂停");
try {
System.out.println("正常暂停 0");
music_2.stop(); //这里有严重的无法更改的错误,但是不影响程序的运行
System.out.println("正常暂停 1");
music_2 = null;
key = false;
}catch(Exception a) {
/**暂停线程时发生错误*/
System.out.println("不正常暂停,或还没有建立一个线程");
//music_2.stop();
key = false;
}
}
- 下一首按钮
/**进行下一首音乐的处理动作*/
public void tonext() {
int i; //这里要查找到当前已经播放到的位置
for(i=0; i<musicList.length; i++) {
if (value == musicList[i]) //value是要用来播放的一个音乐,即当前播放的音乐和列表的音乐匹配一致就跳出,得到数组一直的位置
break;
}
value = musicList[i+1]; //让播放的音乐文件跳到下一个文件
if (value == null) value = musicList[0]; //这里需要判断当前value是不是为空,要是没开始播放就跳转到开头播放
message.setText(""); //清空文本框
message.append(value); //把得到的value即音乐的名称添加到文本框中
System.out.println(value);
tostop(); //首先停止之前播放的线程
torun(rootPaneCheckingEnabled); //开始播放新建立的线程
}
- 最后还有选怎音乐目录的按钮
我建立了五个类联合起来建立这个程序
下面是完整的代码!!!
Main类
package Music_player;
//
//导入原始的awt 组建
import java.awt.Color;
//
import java.awt.Container;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
//
//导入javax里面的swing组建来用来构建窗口
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.WindowConstants;
//
//import java.net.URL;
import java.util.Arrays;
/**建立窗口*/
//
/**查找指定目录下的音乐文件*/
import Music_player.LIstmusic;
import Music_player.MyThread;
//@SuppressWarnings({ "serial", "unused" })
public class Main {
/**声名线程的对象*/
public Thread music;
/**用来传递对象的指针,来在不同的函数里面改变这一个类*/
public Thread music_2;
//MyThread music = new MyThread();
/**用来传递音乐的链接*/
public static String value;
//
/**建立储存播放列表的目录*/
public String[] musicList = {};
//
JButton button_2 = new JButton("开始播放");
//
/**建立一个文本框,文本框里面的内容*/
public JTextArea message; //
//
/**建立一个文本框,文本框里面的内容
* 用来获取目标路径*/
public JTextArea messagePath; //
//
//public static AName aPath;
static AName Path = new AName();
//
//public AName Path = new AName();
/**为建立一个窗口建立的全局变量*/
static JFrame win;
/**为建立一个全局容器建立的变量*/
static Container con;
//
/**构造方法,初始化界面*/
Main(){
/**用来传递音乐的链接*/
//aPath = Path;
//String value;
this.createJFrame("音乐播放器");
System.out.println("建立了主窗口");
}
//
/**作为线程是否运行的的判断标志*/
boolean key = false;//= false;
protected boolean rootPaneCheckingEnabled;
/**让线程开始运行
* @param fouse */
public void torun(boolean fouse) { //函数内的参数时根据错误的处理办法进行自动添加的
//key = true;
if (value == null)return;
try {
if (key) {
System.out.println("已经有一个线程正在播放音乐不能再播放音乐");
return;
}
MyThread music = new MyThread();
music_2= music;
music_2.start();
key = true;
}catch (Exception a) { //这里基本上不会出错误
System.out.println("开始播放音乐错误!或并使用新建线程的方式来播放音乐");
}
}
//
/**让线程停止并且删除*/
@SuppressWarnings("deprecation")
public void tostop() {
System.out.println("开始处理暂停");
try {
System.out.println("正常暂停 0");
music_2.stop(); //这里有严重的无法更改的错误,但是不影响程序的运行
System.out.println("正常暂停 1");
music_2 = null;
key = false;
}catch(Exception a) {
/**暂停线程时发生错误*/
System.out.println("不正常暂停,或还没有建立一个线程");
//music_2.stop();
key = false;
}
}
//
/**进行下一首音乐的处理动作*/
public void tonext() {
int i; //这里要查找到当前已经播放到的位置
for(i=0; i<musicList.length; i++) {
if (value == musicList[i]) //value是要用来播放的一个音乐,即当前播放的音乐和列表的音乐匹配一致就跳出,得到数组一直的位置
break;
}
value = musicList[i+1]; //让播放的音乐文件跳到下一个文件
if (value == null) value = musicList[0]; //这里需要判断当前value是不是为空,要是没开始播放就跳转到开头播放
message.setText(""); //清空文本框
message.append(value); //把得到的value即音乐的名称添加到文本框中
System.out.println(value);
tostop(); //首先停止之前播放的线程
torun(rootPaneCheckingEnabled); //开始播放新建立的线程
}
//
/**建立窗口和主界面*/
void createJFrame(String title) {
//
JFrame win= new JFrame(title); //给win窗口设置一个标题
Container con = win.getContentPane();//给窗口建立一个容器 con
win.setLayout(null); //使用绝对布局
win.setBounds(380,145,334,550);//窗体的位置和大小
//
/**存放所有音乐路径的类*/
LIstmusic myMusicList = new LIstmusic();
/**为了让方便把音乐库的列表传递给这个自己的数组
* 复制数组*/
musicList = Arrays.copyOf(myMusicList.aList, myMusicList.aList.length);
//
/**创建一个列表,用来展示播放音乐的目录*/
JList<String> list_1 = new JList<>(musicList);//创建一个列表
JScrollPane list = new JScrollPane(list_1);//把列表进行创建和滚动条的操作
list.setFont(new Font("微软雅黑",Font.PLAIN,10));
list.setBounds(10,40,300,300); //设置界面的的大小
con.add(list);
//
//
/**建立一个文本框用来存放即将播放选中的的歌曲*/
JTextArea list_2 = new JTextArea();
list_2.setFont(new Font("微软雅黑",Font.PLAIN,15));
list_2.setBounds(10, 350, 300, 25);
con.add(list_2);
message = list_2;
list_2.setText(" welcome! ^v^"); //清空文本框
//
/**建立一个文本框用来存放即将播放选中的的歌曲*/
JTextArea list_3 = new JTextArea();
list_3.setFont(new Font("微软雅黑",Font.PLAIN,15));
list_3.setBounds(10, 10, 200, 25); //224,10, 85, 25
con.add(list_3);
messagePath = list_3;
list_3.append(Path.path); //清空文本框
//
/*
JLabel label = new JLabel("播放列表",JLabel.CENTER); //建立一个标签label
label.setFont(new Font("宋体",Font.PLAIN,17));
label.setBounds(1,10,100,40); //让窗体内的标签文字居中、
con.add(label); //把标签添加到窗口里面 */
//
JLabel label_2 = new JLabel("_____________________________"
+ "___________________________",JLabel.CENTER); //建立一个标签label
label_2.setFont(new Font("微软雅黑",Font.PLAIN,17));
label_2.setBounds(0, 400, 400, 40); //让窗体内的标签文字居中、
con.add(label_2); //把标 签添加到窗口里面
//
JButton button_1 = new JButton("暂停");
button_1.setBounds(10, 450, 86, 40); //设置了按钮的位置和大小
button_1.addActionListener((ActionListener) new ActionListener () { //定义让按钮播放播放器
//@SuppressWarnings("deprecation")
public void actionPerformed(ActionEvent e) {
tostop();
button_2.setText("开始播放");
}
});
con.add(button_1);
//
button_2.setBounds(115, 450, 86, 40); //设置了按钮的位置和大小
button_2.addActionListener((ActionListener) new ActionListener () { //定义让按钮播放播放器
public void actionPerformed(ActionEvent e) {
System.out.println("开始播放音乐");
java.util.List<String> values = list_1.getSelectedValuesList();
System.out.println("选中并得到value是"+values);
list_2.setText(""); //清空文本框
value = values.get(0);//对value进行处理,让它变成字符串
list_2.append(value); //把得到的value即音乐的名称添加到文本框中
System.out.println(value);
torun(rootPaneCheckingEnabled);
button_2.setText("正在播放");
}
});
con.add(button_2);
//
JButton button_3 = new JButton("下一首");
button_3.setBounds(225, 450, 86, 40); //设置了按钮的位置和大小
button_3.addActionListener((ActionListener) new ActionListener () { //定义让按钮播放播放器
//@SuppressWarnings("deprecation")
public void actionPerformed(ActionEvent e) {
tonext();
button_2.setText("正在播放");
}
});
con.add(button_3);
//
JButton button_4 = new JButton("选择");
button_4.setBounds(10, 380, 115, 25); //设置了按钮的位置和大小 10, 350, 300, 25
button_4.addActionListener((ActionListener) new ActionListener () { //定义让按钮播放播放器
public void actionPerformed(ActionEvent e) {
try {
java.util.List<String> values = list_1.getSelectedValuesList();
System.out.println("选中并得到value是"+values);
list_2.setText(""); //清空文本框
value = values.get(0);//对value进行处理,让它变成字符串
list_2.append(value); //把得到的value即音乐的名称添加到文本框中
System.out.println(value);
}catch(Exception a) {
System.out.println("没有选中的目标文件");
tonext();
button_2.setText("正在播放");
}
}
});
con.add(button_4);
//
JButton button_5 = new JButton("清除");
button_5.setBounds(195,380, 115, 25); //设置了按钮的位置和大小
button_5.addActionListener((ActionListener) new ActionListener () { //定义让按钮刷新列表
public void actionPerformed(ActionEvent e) {
System.out.println("刷新列表,清除文本框");
list_2.setText(""); //清空文本框
value = null;
value = "播放内容已经清空";
list_2.append(value);
value = null;
tostop();
button_2.setText("开始播放");
}
});
con.add(button_5);
//
JButton button_6 = new JButton("更换路径");
button_6.setBounds(224,10, 85, 25); //设置了按钮的位置和大小 1,10,100,40 195,380, 115, 25
button_6.addActionListener((ActionListener) new ActionListener () { //定义让按钮刷新列表
public void actionPerformed(ActionEvent e) {
try {
//Path.path = "A:\\study\\music\\";
String mm = list_3.getText();
System.out.println(mm);
Path.path = mm;
con.remove(list);
//System.out.println(value);
/**存放所有音乐路径的类*/
LIstmusic myMusicList = new LIstmusic();
/**为了让方便把音乐库的列表传递给这个自己的数组
* 复制数组*/
musicList = Arrays.copyOf(myMusicList.aList, myMusicList.aList.length);
JList<String> list_1 = new JList<>(musicList);//创建一个列表
JScrollPane list = new JScrollPane(list_1);//把列表进行创建和滚动条的操作
list.setFont(new Font("微软雅黑",Font.PLAIN,10));
list.setBounds(10,40,300,300); //设置界面的的大小
con.add(list);
}catch(Exception a) {
System.out.println("没有选中的目标文件");
}
}
});
con.add(button_6);
con.setBackground(Color.PINK); //设置窗口的颜色
win.setVisible(true); //设置窗口为可见的
win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); //设置窗口的关闭方式
}
/**
* 描 述:作为主类来使用,执行创建窗口创建功能等对象的方法 A:\\music\\可能否 - All Right.mp3
*/
public static void main(String[] args) {
// TODO 自动生成的方法存根
System.out.println("开始建立应用程序");
Main MusicPlayer = new Main();
}
}
第二个类是LIstmusic
package Music_player;
//
import java.io.File;
import java.util.Arrays;
/**z这个类是用来处理再name类里面得到的目标路径,
* 目标路径下的mp3文件找出来*/
public class LIstmusic {
/**字符串数组,储存得到的音乐列表,没有链接*/
public String aList [] = new String [100] ;
/**储存音乐具体路径的数组,直接用于得到音乐的链接*/
public String [] musicList= {};
/**构造函数,进行得到音乐目录的函数,然后对得到的音乐目录进行处理*/
LIstmusic() {
this.getFileList();
this.changeMusic();
}
//public String [] musicList= {};
//JList<String> filelist = new JList<>(fileList);//创建一个列表
/**
* 读取指定路径下的文件名和目录名
*/
public void getFileList() {
/**用于存放目标文件路径的类的对象*/
//AName Path = new AName();
/**建立一个抽象的文件类
* 该类主要用于文件和目录的创建、文件的查找和文件的删除等。
* 还要建立一个用来存放目标路径的类的对象 */
File file = new File(Main.Path.path);
/**返回一个抽象路径名数组,这些路径名表示此抽象路径名所表示目录中的文件。*/
File[] fileList = file.listFiles();
//System.out.println(fileList.length);
//String ML [] = new String [fileList.length] ;
/**遍历生成的数组列表
* 把文件和目录分开打印出来*/
for (int i = 0; i < fileList.length; i++) {
/**查找文件目下的文件*/
if (fileList[i].isFile()) {
String fileName = fileList[i].getName();
//System.out.println("文件:" + fileName);
/**向音乐文件的数组里面添加元素*/
for(int j = 0; j<fileList.length; j++) {
if (aList[j] == null) {
aList[j] = fileName;
break;
}
}
}
/**查找文件目下的目录*/
if (fileList[i].isDirectory()) {
//String fileName = fileList[i].getName();
//System.out.println("目录:" + fileName);
}
}
}
/*
判断是否存在不是mp3的文件
int see(String a) {
int b;
b = a.indexOf("mp3");
if (b != -1) {
return 1;
}
else return 0;
}*/
/**处理得到的音乐的目录*/
void changeMusic() {
String [] bList = {};
bList = Arrays.copyOf(aList, aList.length);
int j =0;
//String filename;
for (int i=0; i< bList.length; i++) {
if (bList[i] != null) {
bList[i] = bList[i];
j++;
}
}
musicList = Arrays.copyOf(bList, j);
//System.out.println((i+1)+"音乐文件有:"+aList[i]);
}
}
第三个线程的类MyFread
package Music_player;
//
import Music_player.text.*;
import Music_player.AName.*;
@SuppressWarnings("unused")
public class MyThread extends Thread {
public void run() {
while (true) {
/*synchronized (this) { //创建线程的挂起区,线程枷锁对象为this
while(AWin.key) {
try {
System.out.println("正在暂停中");
wait();
}catch(InterruptedException e){
System.out.println("暂停时出现错误");
}
}
}*/
/**线程的休眠时间*/
try {
Thread.sleep(1000);
}catch (Exception e) {
System.out.print("线程睡眠错误");
return;
}
/**创建好线程和休眠以后就可以运行音乐了*/
try {
System.out.println("ok,线程正在运行");
text mp3 = new text(Main.value);
mp3.play();
if (Main.value != null) {
mp3 = null;
}
}catch (Exception e) {
System.out.println("线程错误");
}
}
}
}
接下来是定义播放音乐的类text
package Music_player;
//
import javazoom.jl.player.Player; //导入了关于播放音乐的多功能库
import java.io.BufferedInputStream;
import java.io.FileInputStream;
//import java.nio.file.Path;
/**播放音乐的相关的类*/
public class text {
public String value;
/**音乐的名字
* 这个变量的值是在建立的时候通过外部传入参数:.mp3的文件名字来进行赋值的
* */
private String filename;
/**音乐的名字*/
private Player player;
/**构造方法来构建播放音乐名字,通过外部建立对象时传入*/
public text(String filename) {
//AName Path = new AName();
this.filename = Main.Path.path+filename;
//
}
/**播放音乐的方法*/
public void play() {
try {
System.out.println("text正在尝试播放音乐"+filename+"开始播放音乐");
BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(filename));
player = new Player(buffer);
player.play();
} catch (Exception e) {
System.out.println(e);
}
}
}
//
最后一个是一个文件路径的类 方便后期的更改 AName
package Music_player;
//
/**建立一个储存文件的上层具体目录路径的类,用来代替后期的文件路路径的方便*/
public class AName {
/**建立一个文件路径用来存放目标文件*/
public String path;
/**构造方法
* 在建立路径的对象的时候如果没有设置参数就会默认选择在"A:\\music\\"路径下*/
AName(){
this.path = "music\\";
}
/**重构构造方法,用来存放如果不是制定路径的方法*/
AName(String path){
this.path = path;
}
}
代码总共四百行吧,用了三天时间,爽快。