借鉴了一些java IO流编程技巧,自制了一个可以导入本地,wav格式的java音乐播放器。
目前做完的1.0版本主窗体JFrame?菜单栏功能还没有写设计完整,后续版本会赋予功能以及实现更加美观动态的GUI界面,以及后续音乐歌词功能实现。后续版本会实现.mp3等多种格式音乐播放功能。(.wav格式的音频可以通过格式转换工具l来变成,我用的工具软件:格式工厂(不收费))
话不多说进入正题:》》》》》》》
本播放器实现开启了多个线程以及线程内部类,每个类几乎都有实现Runnable接口执行run方法。
先上GUI主要架构:
本音乐播放器一共4个类:
一丶主窗体JFrame类:MusicPlayer ,继承了JFrame并实现了Runnable接口。(其中菜单条JmenuBar还没有写功能可以忽略)
二丶左面板类:JPanelL,继承了JPanel。
三丶右面板类:JPanelR,继承了JPanel也实现了Runnable接口。
四丶下面板类:JPanelS,继承了JPanel也实现了Runnable接口。
主方法在MusicPlayer中,刚运行时如下
点击“导入本地音乐”后出现一个Dialog资源管理器窗口来选择音乐,本层目录是.wav格式的音乐会加载到JPanelL面板的List列表中,之后单击选中音乐列表的一项然后单击JPanelS面板中的 播放按钮 便可以播放音乐。播放后会出现 暂停按钮 和 继续按钮。播放后JPanelR面板和JPanelS面板会重新绘制成gif动态背景,点击暂停时则回复原始背景。
主窗体类 MusicPlayer 代码
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.MenuShortcut;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
public class MusicPlayer extends JFrame //本类菜单有关的组件没有设置功能可不看 直接去看里面的3个JPanel面板
{
JPanelL jpanell; //主窗体左边面板
JPanelR jpanelr; //主窗体右边面板
JPanelS jpanels; //主窗体下面面板
JMenuBar jmenubar;//菜单条
JMenu jmenu1, jmenu2, jmenu3;//菜单
JMenuItem jmenu1item1, jmenu1item2, jmenu1item3;//菜单中的菜单项
public MusicPlayer()
{
this.setTitle("Java音乐播放器1.0");
this.setLayout(new GridBagLayout());
jpanell=new JPanelL();//实例化面板对象
jpanelr=new JPanelR();
jpanels=new JPanelS();
jmenubar=new JMenuBar();//菜单条
jmenubar.getComponent().setBackground(Color.ORANGE);
jmenubar.setMargin(new Insets(100,20, 50, 50));
jmenu1=new JMenu("文件(A)");//菜单1
jmenu1.setIcon(new ImageIcon(Toolkit.getDefaultToolkit().getImage("res/文件菜单图标.jpg")));
jmenu1item1=new JMenuItem("打开");//菜单项1
jmenu1.add(jmenu1item1);//在菜单1中添加菜单项1
jmenu1.addSeparator();//在菜单1中的菜单项1的后面添加一条分割线 下面以此类推
jmenu1item2=new JMenuItem("关闭");
jmenu1.add(jmenu1item2);
jmenu1.addSeparator();
jmenu1item3=new JMenuItem("搜索");
jmenu1.add(jmenu1item3);
jmenubar.add(jmenu1);//菜单条添加菜单1
jmenubar.setMargin(new Insets(100,20, 50, 50));
jmenu2=new JMenu("工具(B)");//菜单2
jmenu2.setIcon(new ImageIcon(Toolkit.getDefaultToolkit().getImage("res/工具菜单图标.jpg")));
jmenubar.add(jmenu2);
jmenubar.setMargin(new Insets(100,20, 50, 50));
jmenu3=new JMenu("其他(C)");//菜单3
jmenu3.setIcon(new ImageIcon(Toolkit.getDefaultToolkit().getImage("res/其他菜单图标.jpg")));
jmenubar.add(jmenu3);
GridBagConstraints g=new GridBagConstraints();
g.gridx=0;
g.gridy=0;
g.gridwidth=1;
g.gridheight=1;
g.weightx=0.3;
g.weighty=0.8;
g.fill = GridBagConstraints.BOTH;
this.getContentPane().add(jpanell, g);
g.gridx=1;
g.gridy=0;
g.gridwidth=1;
g.gridheight=1;
g.weightx=0.7;
g.weighty=0.8;
g.fill = GridBagConstraints.BOTH;
this.getContentPane().add(jpanelr, g);
g.gridx=0;
g.gridy=1;
g.gridwidth=2;
g.gridheight=1;
g.weightx=1.0;
g.weighty=0.2;
g.fill = GridBagConstraints.BOTH;
this.getContentPane().add(jpanels, g);
this.setJMenuBar(jmenubar);//将菜单条加入到容器
this.setBounds(200,50,1200,700);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String args[])
{
MusicPlayer mu=new MusicPlayer();
}
}
下面板类 JPanelS(此类是最重要的一个类实现了IO流控制来播放音乐)部分代码如下
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Label;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class JPanelS extends JPanel implements Runnable
{
public String jplsbackpath="res/jps.jpg";//JPanelS背景图片路径
JPanelS jpls;
JLabel jls;
JButton jb; //播放按钮
JButton jbz;//播放暂停按钮
JButton jbx;//播放下一曲按钮
JButton jbs;//播放上一曲按钮
JButton jbt;//退出按钮
int i=1;
String filenamelS=null;
String filepathlS=null;
public static boolean BOZ=false;//是否暂停或继续播放
public static boolean BO=false;//是否成功播放 线程中会触发更换播放时的动态背景
public static boolean BT=false;//是否播放失败或播放结束 线程中会触发更换静态背景
public boolean ThreadStop=true;//缓存线程停止
public boolean ThreadBreak=true;//缓存线程退出
public AudioInputStream audioinputstream;//声音输入流
public AudioFormat audioFormat;// 文件格式
public SourceDataLine sourceDataLine;// 输出设备
public File audiofile;//音乐播放文件
public JPanelS()
{
this.setLayout(new GridBagLayout());
GridBagConstraints g=new GridBagConstraints();
g.gridx=0;
g.gridy=0;
g.gridwidth=1;
g.gridheight=1;
g.insets=new Insets(0,50,0,0);
jb = new JButton("播放");
jb.setSize(100,100);
jb.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
filenamelS = new String(JPanelL.filename);//获取左边面板的文件名
filepathlS = new String(JPanelL.filepath);//获取所在目录
}
catch(Exception e1)
{
if(JPanelL.filepath==null)
JOptionPane.showMessageDialog(null, "没有导入音乐文件路径!");
if((JPanelL.filepath!=null)&&(JPanelL.filename==null))
JOptionPane.showMessageDialog(null, "没有选择要播放的音乐!");
}
if((filenamelS!=null) || (filepathlS!=null)) //如果播放路径不为空
{
try
{
BOZ=false;
play();//启动 音乐播放方法
jbz.setText("暂停播放");
jbz.setVisible(true);
BO=true;
JPanelR.BO2=true;
jbz.setText("暂停播放");
System.out.println("play启动成功"+BO+BT);
}
catch (UnsupportedAudioFileException | IOException | LineUnavailableException e1)
{
BT=true;
JPanelR.BT2=true;
jbz.setText("暂停播放");
JOptionPane.showMessageDialog(null, "播放格式错误请重新选择!");
System.out.println("play启动失败"+BO+BT);
}
}
}
});
this.add(jb, g);
jbz=new JButton("暂停播放");
jbz.setVisible(false);
jbz.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String jbzs=jbz.getText();
if(jbzs.equals("暂停播放"))
{
BOZ=true;
BT=true;
JPanelR.BT2=true;
jbz.setText("继续播放");
jb.setVisible(false);
}
if(jbzs.equals("继续播放"))
{
BOZ=false;
BO=true;
JPanelR.BO2=true;
jbz.setText("暂停播放");
jb.setVisible(true);
}
}
});
g.gridx=1;
g.gridy=0;
g.gridwidth=1;
g.gridheight=1;
this.add(jbz, g);
jbs=new JButton("上一曲");//目前没有赋予功能
g.gridx=2;
g.gridy=0;
g.gridwidth=1;
g.gridheight=1;
//this.add(jbs, g);
jbx=new JButton("下一曲");//目前没有赋予功能
g.gridx=3;
g.gridy=0;
g.gridwidth=1;
g.gridheight=1;
//this.add(jbx, g);
jbt=new JButton("退出");
jbt.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
g.gridx=4;
g.gridy=0;
g.gridwidth=1;
g.gridheight=1;
this.add(jbt, g);
new Thread(this).start();
}
public void play() throws UnsupportedAudioFileException,IOException,LineUnavailableException//音乐播放方法
{
ThreadBreak=true;// 停止播放线程
while (!ThreadStop)
{
try
{
Thread.sleep(10);
}
catch (Exception e)
{
}
}
audiofile = new File(filepathlS+filenamelS);//获取用户选中的文件
JPanelL.labelfilename.setText("播放文件:" + filenamelS);//左边面板显示正在播放的音乐文件
// 取得文件输入流
audioinputstream = AudioSystem.getAudioInputStream(audiofile);
audioFormat = audioinputstream.getFormat();
// 转换mp3文件编码
if (audioFormat.getEncoding() != AudioFormat.Encoding.PCM_SIGNED) {
audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
audioFormat.getSampleRate(), 16, audioFormat
.getChannels(), audioFormat.getChannels() * 2,
audioFormat.getSampleRate(), false);
audioinputstream = AudioSystem.getAudioInputStream(audioFormat,
audioinputstream);
}
// 打开输出设备
DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, audioFormat,AudioSystem.NOT_SPECIFIED);
sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
sourceDataLine.open(audioFormat);
sourceDataLine.start();
// 创建独立线程进行播放
ThreadBreak=false;
Thread threadplay = new Thread(new ThreadPlay());
threadplay.start();//开启新的播放线程
}
public void paintComponent(Graphics g) //重写JPanel背景方法
{
JLabel j=new JLabel(jplsbackpath);
ImageIcon Imajpls=new ImageIcon(jplsbackpath);
g.drawImage(Imajpls.getImage(), 0, 0, this.getSize().width, this.getSize().height, this);
System.out.println("是否调用paintComponent"+"-------"+i);
i++;
}
class ThreadPlay extends Thread //音乐播放方法的 音乐资源缓存线程内部类
{
byte tempBuffer[] = new byte[320];
public void run()
{
try
{
int cnt;
ThreadStop = false;
// 读取数据到缓存数据
while ((cnt = audioinputstream.read(tempBuffer, 0,tempBuffer.length)) != -1)
{
if (ThreadBreak)
break;
if (cnt > 0)
{
sourceDataLine.write(tempBuffer, 0, cnt);// 写入缓存数据
}
while(BOZ)
{
System.out.println();
}
}
// Block等待临时数据被输出为空
sourceDataLine.drain();
sourceDataLine.close();
BT=true;
JPanelR.BT2=true;
ThreadStop = true;
}
catch (Exception e)
{
e.printStackTrace();
System.exit(0);
}
}
}
@Override
public void run()
{
System.out.println("JPanlS线程执行");
while(true)
{
System.out.println();
if(BO)
{
System.out.println("BO执行");
jplsbackpath="res/jps1.gif";
repaint();
BO=false;
}
if(BT)
{
System.out.println("BT执行");
jplsbackpath="res/jps.jpg";
repaint();
BT=false;
}
}
}
}
现在为1.0版本后续我会将它慢慢升级成为GUI更加美观,操作感强,功能更强大的音乐播放器 ?注:其他类完整代码以及资源包可以联系我QQ:740458078
|