建立這個播放器的簡單思想就是使用線程和界面同時運行,達到播放和界面按鈕的功能。
做好的界面如下:
- 使用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;
}
}
代碼總共四百行吧,用了三天時間,爽快。