Java 实验- Swing 音乐播放器
实验要求:
综合利用Swing界面和自己写音乐播放类,设计音乐播放器如下:
(1)纯Swing给定的组件可以设计出一个普通的音乐播放器界面。如果有PS功底或者想追求界面的绚丽,素材可以自己设计也可以通过自己渠道寻求美工帮助。主要是按钮,进度条,标签等显示效果。
![](https://img2023.cnblogs.com/blog/2935791/202303/2935791-20230306194413191-1125984922.png)
(2)音乐播放方面,不能调用其他第三方jar包,只能用JDK底层自带的API类,例如JavaSound。使用JavaSound API,可以实现各种基于声音的应用,例如声音录制、音乐播放、网络电话、音乐编辑等。JavaSound API又以各种解码和合成器SPI(服务提供者接口, Service Provider Interface)为基础,实现各种音乐格式的解码与转码。
说明:
纯属是为了应付实验要求,写了一坨屎山代码,如果有需要的可以去应付一下hh
代码:
音乐播放器MusicPlayer类:
package com.junlin.exer10;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.SourceDataLine;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/**
* @Description:
* @author: junlin623
* @create: 2022-11-25 17:20
*/
public class MusicPlayer {
private File file; //音频的路径
// 是否循环播放
private volatile boolean isLoop = false;
// 是否正在播放
private volatile boolean isPlaying = false;
float newVolumn = 7; //音量
private PlayThread playThread; //音乐播放线程
private MusicPlayer musicPlayer = this;
private MyFrame host; //依附的主界面
public MusicPlayer(MyFrame host, File file) {
this.host = host;
this.file = file;
if(!this.file.exists()) {
System.out.println("文件不存在");
System.exit(0);
}
}
/**
* 播放音乐
*/
public void play() {
//新建一个播放音乐的线程
if(playThread != null) playThread.stop(); //当点击开始会从头开始播放音乐
playThread = new PlayThread();
playThread.start();
}
/**
* 结束音乐(并非暂停)
*/
public void over() {
isPlaying = false;
if (playThread != null) {
playThread = null;
}
}
/**
* 设置循环播放
* @param isLoop
* @return 返回当前对象
*/
public MusicPlayer setLoop(boolean isLoop) {
this.isLoop = isLoop;
return this;
}
/**
* -80.0~6.0206测试,越小音量越小
* @param newVolumn
* @return 返回当前对象
*/
public MusicPlayer setVolumn(float newVolumn) {
this.newVolumn = newVolumn;
return this;
}
/**
* 设置是否进行播放
* @param playing
*/
public void setPlaying(boolean playing) {
isPlaying = playing;
}
// 暂停播放音频
public void stopMusic() {
synchronized (this) {
isPlaying = false;
notifyAll();
}
}
// 继续播放音乐
public void continueMusic() {
synchronized (this) {
isPlaying = true;
notifyAll();
}
}
/**
* 异步播放线程
*/
private class PlayThread extends Thread {
@Override
public void run() {
isPlaying = true;
while(true) {
SourceDataLine sourceDataLine = null;
BufferedInputStream bufIn = null;
AudioInputStream audioIn = null;
try {
bufIn = new BufferedInputStream(new FileInputStream(file));
audioIn = AudioSystem.getAudioInputStream(bufIn); // 可直接传入file
AudioFormat format = audioIn.getFormat();
sourceDataLine = AudioSystem.getSourceDataLine(format);
sourceDataLine.open();
// 必须open之后
sourceDataLine.start();
byte[] buf = new byte[512];
// System.out.println(audioIn.available());
int len = -1;
int cnt = 0;
while ((len = audioIn.read(buf)) != -1) {
synchronized (musicPlayer) {
while(!isPlaying) { //如果停止播放了就让该线程等待
musicPlayer.wait();
}
if (newVolumn != 7) {
FloatControl control = (FloatControl) sourceDataLine.getControl(FloatControl.Type.MASTER_GAIN);
//调节音量
System.out.println("当前音量:" + newVolumn);
control.setValue(newVolumn);
}
}
cnt += len;
System.out.println("now: " + cnt);
System.out.println((1.0*cnt) / host.length);
host.progressBar.setString("" + (int)((1.0*cnt) / host.length * 100) + "%");
host.progressBar.setValue(cnt);
host.progressBar.paintImmediately(host.progressBar.getBounds());
sourceDataLine.write(buf, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sourceDataLine != null) {
sourceDataLine.drain();
sourceDataLine.close();
}
try {
if (bufIn != null) {
bufIn.close();
}
if (audioIn != null) {
audioIn.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
鼠标事件监听类ButtonHandler类:
package com.junlin.exer10;
import javax.swing.JButton;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* @Description:
* @author: junlin623
* @create: 2022-11-27 14:15
*/
public class ButtonHandler implements ActionListener {
private MyFrame window;
private MusicPlayer musicPlayer;
public ButtonHandler(MyFrame window, MusicPlayer musicPlayer) {
this.window = window;
this.musicPlayer = musicPlayer;
}
@Override
public void actionPerformed(ActionEvent e) {
JButton sourceBtn = (JButton) e.getSource();
if(sourceBtn == this.window.playBtn) {
//开始播放
// this.musicPlayer.startMusic();
this.musicPlayer.play();
}else if(sourceBtn == this.window.stopBtn) {
//暂停
this.musicPlayer.stopMusic();
}else {
//继续播放
this.musicPlayer.continueMusic();
}
}
}
主界面MyFrame.java中的两个类:主界面类MyFrame; 定时器类ChangeImageTask
package com.junlin.exer10;
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;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.List;
import java.io.File;
import java.util.Timer;
import java.util.TimerTask;
/**
* @Description:
* @author: junlin623
* @create: 2022-11-27 14:11
*/
public class MyFrame extends JFrame {
JButton playBtn; //开始按钮
JButton stopBtn; //暂停按钮
JButton continueBtn; //继续按钮
MusicPlayer player; //音乐播放器
JProgressBar progressBar; //进度条
File file = null; //音乐文件
String filepath = "D:/onedrive/桌面/Java学习/Java作业/实验/实验九/实验9-音乐播放器/resource/";
long length; //表示文件的总字节长度
JLabel imageLabel; //顶部图片标签
JLabel musicLabel; //音量显示标签
int cnt = 1; //当前选择的顶部图片编号
public MyFrame() {
super("音乐播放器");
file = new File("D:\\onedrive\\桌面\\Java学习\\Java作业\\实验\\实验九\\实验9-音乐播放器\\resource\\test.wav");
length = file.length(); //获取文件的字节大小
System.out.println("length = " + length);
initMusicPlayer(); //初始化音乐播放器
Container contentPane = this.getContentPane();
contentPane.setBackground(Color.white);
contentPane.setLayout(null);
//顶部轮播图
imageLabel = new JLabel();
imageLabel.setIcon(new ImageIcon(filepath + "b" + cnt + ".png"));
imageLabel.setBounds(50,10,700,200);
contentPane.add(imageLabel);
Timer timer = new Timer();
timer.schedule(new ChangeImageTask(this), 0, 1500);
//上方进度条和按钮区域
JPanel topPanel = new JPanel();
topPanel.setLayout(null);
topPanel.setBounds(50,220,700,200);
topPanel.setBackground(Color.WHITE);
contentPane.add(topPanel);
Border border1 = BorderFactory.createTitledBorder("播放进度");
topPanel.setBorder(border1);
//添加进度条
progressBar = new JProgressBar();
progressBar.setIndeterminate(false);
progressBar.setMaximum((int)length);
progressBar.setStringPainted(true);
progressBar.setString("0%");
progressBar.setBounds(20,30,650,20);
topPanel.add(progressBar);
//添加按钮
playBtn = new JButton("播放");
stopBtn = new JButton("暂停");
continueBtn = new JButton("继续");
playBtn.addActionListener(new ButtonHandler(this, player));
stopBtn.addActionListener(new ButtonHandler(this, player));
continueBtn.addActionListener(new ButtonHandler(this, player));
playBtn.setBounds(150,80,80,30);
stopBtn.setBounds(270,80,80,30);
continueBtn.setBounds(370,80,80,30);
topPanel.add(playBtn);
topPanel.add(stopBtn);
topPanel.add(continueBtn);
//下方音量控制区域
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(null);
bottomPanel.setBackground(Color.white);
bottomPanel.setBounds(50,450,700,200);
contentPane.add(bottomPanel);
Border border2 = BorderFactory.createTitledBorder("音量控制");
bottomPanel.setBorder(border2);
musicLabel = new JLabel("当前音量大小: 100");
musicLabel.setBounds(10,30,150,20);
bottomPanel.add(musicLabel);
JSlider slider=new JSlider(0,100,100);
slider.setBackground(Color.white);
slider.setMajorTickSpacing(10);//此方法设置主刻度标记的间隔
slider.setMinorTickSpacing(5);//设置次刻度标记的间隔
slider.setPaintLabels(true);//确定是否在滑块上绘制标签
slider.setPaintTicks(true);//确定是否在滑块上绘制刻度标记
slider.setBounds(20,80,600,80);
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
// System.out.println("当前值:" + slider.getValue());
synchronized (player) {
// System.out.println("当前音量:" + player.newVolumn);
musicLabel.setText("当前音量大小:" + slider.getValue());
player.newVolumn = -80.0f + 0.86f * slider.getValue();
}
}
});
bottomPanel.add(slider);
this.setSize(new Dimension(800,900));
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void initMusicPlayer() {
try {
player = new MusicPlayer(this, file);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//轮播图定时器
class ChangeImageTask extends TimerTask {
private MyFrame frame;
public ChangeImageTask(MyFrame frame) {
this.frame = frame;
}
@Override
public void run() {
this.frame.cnt += 1;
if(this.frame.cnt >= 6){
this.frame.cnt = 1;
}
this.frame.imageLabel.setIcon(new ImageIcon(this.frame.filepath + "b" + this.frame.cnt + ".png"));
//frame.imageLabel.paintImmediately(frame.imageLabel.getBounds());
}
}
JavaMain类:
package com.junlin.exer10;
/**
* @Description:
* @author: junlin623
* @create: 2022-11-27 14:10
*/
public class JavaMain {
public static void main(String[] args) {
new MyFrame();
}
}
运行结果:
你只管出发,旅途自有风景~~