java實(shí)現(xiàn)音樂播放器完整代碼(調(diào)整顯示音量大小、調(diào)整進(jìn)度、圖片切換)
上學(xué)期老師布置了一個(gè)音樂播放器的作業(yè),自己獨(dú)立寫的界面感覺還行就傳上來了。
package Music;
import javax.sound.sampled.*;
import java.io.*;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JSlider;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Musicrun {
JFrame frame = new JFrame("音樂播放器");
JPanel p1 = new JPanel();
JPanel p2 = new JPanel();
JPanel p3 = new JPanel();
Border etched = BorderFactory.createEtchedBorder();
Border border = BorderFactory.createTitledBorder(etched, "");
JButton jButton1 = new JButton("Start");
JButton jButton2 = new JButton("Stop");
JButton jButton3 = new JButton("Continue");
boolean bofang = false;
JLabel yinliang = new JLabel();
JLabel musicImage = new JLabel();
float ylforce = 0;
double atime = 0;
double bftime = 0;
public String musicPath = "D:\\zuoye\\java\\resource\\test.wav";
public AudioPlayer music = null;
JSlider slider1 = new JSlider();
JProgressBar progressBar = new JProgressBar();
ImageIcon icon[] = { new ImageIcon("D:\\zuoye\\java\\resource\\b1.png"),
new ImageIcon("D:\\zuoye\\java\\resource\\b2.png"),
new ImageIcon("D:\\zuoye\\java\\resource\\b3.png"),
new ImageIcon("D:\\zuoye\\java\\resource\\b4.png"),
new ImageIcon("D:\\zuoye\\java\\resource\\b5.png") };
public Musicrun() {
frame.setSize(800, 800);
frame.setLayout(new GridLayout(3, 1));
border = BorderFactory.createTitledBorder("播放進(jìn)度");
p2.setBorder(border);
border = BorderFactory.createTitledBorder("音量控制");
p3.setBorder(border);
init();
frame.getContentPane().add(p1);
frame.getContentPane().add(p2);
frame.getContentPane().add(p3);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private void init() {
// p1部分
musicImage.setIcon(icon[0]);
p1.add(musicImage);
Timer timer = new Timer();
// timer.schedule(new MusicTask(), 500,1000);
timer.schedule(new MusicTask(), 500, 2000);
// p2部分
music = new AudioPlayer(musicPath);
progressBar.setMaximum(100);
progressBar.setMinimum(0);
progressBar.setStringPainted(true);
progressBar.setIndeterminate(false);
progressBar.setPreferredSize(new Dimension(780, 30));
;
;
p2.add(progressBar);
Timer timer2 = new Timer();
timer2.schedule(new MusicTask2(), 0, 100);
jButton1.setSize(80, 40);
jButton2.setSize(80, 40);
jButton3.setSize(80, 40);
p2.add(jButton1);
p2.add(jButton2);
p2.add(jButton3);
jButton1.addActionListener(new ButtonHandler());
jButton2.addActionListener(new ButtonHandler1());
jButton3.addActionListener(new ButtonHandler2());
// p3部分
yinliang.setText("當(dāng)前音量為:" + slider1.getValue());
// yinliang.setBounds(0,630,100,20);
p3.setLayout(new BorderLayout());
p3.add(yinliang, BorderLayout.WEST);
slider1.setValue(100);
slider1.setPaintTicks(true);// setPaintTicks()方法是設(shè)置是否在JSlider加上刻度,若為true則下面兩行才有作用。
slider1.setMajorTickSpacing(20);
slider1.setMinorTickSpacing(5);
slider1.setPaintLabels(true);// setPaintLabels()方法為設(shè)置是否數(shù)字標(biāo)記,若設(shè)為true,則JSlider刻度上就會(huì)有數(shù)值出現(xiàn)。
slider1.setPaintTrack(true);// setPaintTrack()方法表示是否出現(xiàn)滑動(dòng)桿的橫桿。默認(rèn)值為true.
slider1.setSnapToTicks(true);// setSnapToTicks()方法表示一次移動(dòng)一個(gè)小刻度,而不再是一次移動(dòng)一個(gè)單位刻度。
// JLabel label1 = new JLabel("目前刻度:" + );
slider1.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
yinliang.setText("當(dāng)前音量:" + slider1.getValue());
ylforce = (float) ((0.86) * slider1.getValue() - 80);
music.setVol(ylforce);
}
});
p3.add(slider1, BorderLayout.SOUTH);
}
public class MusicTask extends TimerTask {
// TODO 自動(dòng)生成的方法存根
int i = 0;
@Override
public void run() {
musicImage.setIcon(icon[i]);
i++;
if (i == 5) {
i = 0;
}
}
}
public class MusicTask2 extends TimerTask {
// TODO 自動(dòng)生成的方法存根
// double progressValues;
int progressBarValues;
@Override
public void run() {
if (bofang == true) {
bftime += 0.1;
progressBarValues = (int) ((bftime / atime) * 100);
progressBar.setValue(progressBarValues);
}
}
}
private class ButtonHandler implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (bofang == false) {
bofang = true;
bftime = 0;
music.start(bofang);
} else {
music.start(bofang);
}
}
}
private class ButtonHandler1 implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (bofang == true) {
bofang = false;
music.stop();
} else {
music.stop();
}
}
}
private class ButtonHandler2 implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (bofang == false) {
bofang = true;
music.continues();
} else {
music.continues();
}
}
}
public class AudioPlayer {
private String musicPath; // 音頻文件
private volatile boolean run = true; // 記錄音頻是否播放
private Thread mainThread; // 播放音頻的任務(wù)線程
private float newVolumn = 7;
private AudioInputStream audioStream;
private AudioFormat audioFormat;
private SourceDataLine sourceDataLine;
public AudioPlayer(String musicPath) {
this.musicPath = musicPath;
prefetch();
}
// 數(shù)據(jù)準(zhǔn)備
private void prefetch() {
try {
// 獲取音頻輸入流
audioStream = AudioSystem.getAudioInputStream(new File(musicPath));
// 獲取音頻的編碼對(duì)象
audioFormat = audioStream.getFormat();
// 包裝音頻信息
DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, audioFormat,
AudioSystem.NOT_SPECIFIED);
// 使用包裝音頻信息后的Info類創(chuàng)建源數(shù)據(jù)行,充當(dāng)混頻器的源
sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
// 獲得音頻的總時(shí)長(zhǎng)
atime = audioStream.getFrameLength() / audioFormat.getSampleRate();
sourceDataLine.open(audioFormat);
sourceDataLine.start();
} catch (UnsupportedAudioFileException ex) {
ex.printStackTrace();
} catch (LineUnavailableException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
// 析構(gòu)函數(shù):關(guān)閉音頻讀取流和數(shù)據(jù)行
protected void finalize() throws Throwable {
super.finalize();
sourceDataLine.drain();
sourceDataLine.close();
audioStream.close();
}
// 播放音頻:通過loop參數(shù)設(shè)置是否循環(huán)播放
private void playMusic(boolean loop) throws InterruptedException {
try {
if (loop) {
while (true) {
playMusic();
bftime = 0;
}
} else {
playMusic();
// 清空數(shù)據(jù)行并關(guān)閉
sourceDataLine.drain();
sourceDataLine.close();
audioStream.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
private void playMusic() {
try {
synchronized (this) {
run = true;
}
// 通過數(shù)據(jù)行讀取音頻數(shù)據(jù)流,發(fā)送到混音器;
// 數(shù)據(jù)流傳輸過程:AudioInputStream -> SourceDataLine;
audioStream = AudioSystem.getAudioInputStream(new File(musicPath));
int count;
byte tempBuff[] = new byte[1024];
while ((count = audioStream.read(tempBuff, 0, tempBuff.length)) != -1) {
synchronized (this) {
while (!run)
wait();
}
sourceDataLine.write(tempBuff, 0, count);
}
} catch (UnsupportedAudioFileException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
// 暫停播放音頻
private void stopMusic() {
synchronized (this) {
run = false;
notifyAll();
}
}
// 繼續(xù)播放音樂
private void continueMusic() {
synchronized (this) {
run = true;
notifyAll();
}
}
// 外部調(diào)用控制方法:生成音頻主線程;
public void start(boolean loop) {
mainThread = new Thread(new Runnable() {
public void run() {
try {
playMusic(loop);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
mainThread.start();
}
// 外部調(diào)用控制方法:暫停音頻線程
public void stop() {
new Thread(new Runnable() {
public void run() {
stopMusic();
}
}).start();
}
// 外部調(diào)用控制方法:繼續(xù)音頻線程
public void continues() {
new Thread(new Runnable() {
public void run() {
continueMusic();
}
}).start();
}
// 播放器的狀態(tài)
public boolean isPlaying() {
return run;
}
// 設(shè)置音頻音量
// https://zhidao.baidu.com/question/269020584.html
public void setVol(float value) {
newVolumn = value;
// 必須open之后
if (newVolumn != 7) {
FloatControl control = (FloatControl) sourceDataLine.getControl(FloatControl.Type.MASTER_GAIN);
// System.out.println(control.getMaximum());
// System.out.println(control.getMinimum());
control.setValue(newVolumn);
}
}
// 銷毀
public void destroy() {
try {
finalize();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}然后底下是主函數(shù)
package Music;
public class JavaMain {
public static void main(String[] args) {
// TODO 自動(dòng)生成的方法存根
new Musicrun();
}
}關(guān)于進(jìn)度條進(jìn)度的問題,可以利用計(jì)時(shí)器統(tǒng)計(jì)當(dāng)前已經(jīng)播放的時(shí)間。然后利用函數(shù)計(jì)算音樂播放的總時(shí)間。兩者相除就能得出當(dāng)前的進(jìn)度了。
總結(jié)
到此這篇關(guān)于java實(shí)現(xiàn)音樂播放器的文章就介紹到這了,更多相關(guān)java音樂播放器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java基礎(chǔ)教程之獲取操作系統(tǒng)及瀏覽器信息
最近在開發(fā)中需要從request中獲取操作系統(tǒng),瀏覽器及瀏覽器版本信息,所以下面這篇文章主要給的大家介紹了關(guān)于Java基礎(chǔ)教程之獲取操作系統(tǒng)及瀏覽器信息的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-10-10
java中 IO 常用IO操作類繼承結(jié)構(gòu)分析
本篇文章小編為大家介紹,java中 IO 常用IO操作類繼承結(jié)構(gòu)分析。需要的朋友參考下2013-04-04
Java使用Statement接口執(zhí)行SQL語句操作實(shí)例分析
這篇文章主要介紹了Java使用Statement接口執(zhí)行SQL語句操作,結(jié)合實(shí)例形式詳細(xì)分析了Java使用Statement接口針對(duì)mysql數(shù)據(jù)庫(kù)進(jìn)行連接與執(zhí)行SQL語句增刪改查等相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2018-07-07
Java多線程的調(diào)度_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
有多個(gè)線程,如何控制它們執(zhí)行的先后次序呢?下文給大家分享四種方法及java多線程調(diào)度的實(shí)例代碼,需要的朋友參考下吧2017-05-05
詳解Spring Security的formLogin登錄認(rèn)證模式
對(duì)于一個(gè)完整的應(yīng)用系統(tǒng),與登錄驗(yàn)證相關(guān)的頁(yè)面都是高度定制化的,非常美觀而且提供多種登錄方式。這就需要Spring Security支持我們自己定制登錄頁(yè)面,也就是本文給大家介紹的formLogin模式登錄認(rèn)證模式,感興趣的朋友跟隨小編一起看看吧2019-11-11
Spring中WebClient的創(chuàng)建和使用詳解
這篇文章主要介紹了Spring中WebClient的創(chuàng)建和使用詳解,在Spring5中,出現(xiàn)了Reactive響應(yīng)式編程思想,并且為網(wǎng)絡(luò)編程提供相關(guān)響應(yīng)式編程的支持,如提供了WebFlux,它是Spring提供的異步非阻塞的響應(yīng)式的網(wǎng)絡(luò)框架,需要的朋友可以參考下2023-11-11
idea快速搭建spring cloud注冊(cè)中心與注冊(cè)的方法
這篇文章主要介紹了idea快速搭建spring cloud注冊(cè)中心與注冊(cè)的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-07-07

