前言
上个寒假小编用python做了一个音乐播放软件(博客链接为:)运用tkinter、爬虫做了一个播放音乐的小程序(动态显示歌词【歌词向上翻滚】),觉得效果不怎么的,于是今天小编用Java做了一个播放软件,个人觉得这个有了一点质的飞跃,毕竟python图形界面从某些方面讲不如Java。在这里声明一下:本编文章仅供学习,切莫用于商业活动,一经被相关人员发现,本小编概不负责!希望读者切记!!
运用Java实现音乐播放器
虽然我题目讲的是运用Java做的,但是还是用到了python,而且python的部分很重要,所以小编首先讲的是需要的python模块。
需要的模块有requests、sys、urllib.parse、json
其中requests和urllib.parse主要用于爬取歌曲信息用的,json数据用于解析得到的json数据,sys主要用于传递参数用的。
还记得如下这个吗?
from sys import argv
sum=int(argv[1])+int(argv[2])
print(sum)
首先,在给出代码之前,我想讲一下具体是怎样实现这个播放软件的,小编是写了两个python代码程序,分别为music2.py和music.py,music2.py通过传入的歌曲名称,会产生两个.txt文件,分别存储搜索得到的歌曲信息和与之对应的歌曲id和hash值,music.py通过传入的歌曲id和hash值下载歌曲和歌词.
然后写了两个Java线程让播放歌曲和歌词流动同步(不设置线程只能等其中的任何一个结束之后才能执行另外一个)。
当然,读者在看小编下面的两个代码的时候,或许会存在一些疑问,小编在这里先给出另外一边博客的地址,看了这篇博客,读者应该会理解两个python代码程序的作用了。博客链接为:酷狗音乐
参考代码如下:
music2.py
from sys import argv
from urllib.parse import quote
import requests
import json
keyword=argv[1]
encodeName=quote(keyword)
url='https://songsearch.kugou.com/song_search_v2?callback=jQuery1124042761514747027074_1580194546707&keyword=%s&page=1&pagesize=30&userid=-1&clientver=&platform=WebFilter&tag=em&filter=2&iscorrection=1&privilege_filter=0&_=1580194546709'%(encodeName)
headers={
'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3756.400 QQBrowser/10.5.4039.400'}
response=requests.get(url=url,headers=headers)
str2=response.text
str2 = str2[str2.find('(') + 1:str2.rfind(')')]
dict2 = json.loads(str2)
music_list = dict2['data']['lists']
hash_list = list()
musicNames=list()
for id in range(len(music_list)):
music_name=music_list[id]['FileName'].replace('', '').replace('', '')
musicNames.append(music_name)
hash_list.append([music_list[id]['FileHash'],music_list[id]['AlbumID']])
with open(file='D:/intell/Clock/src/file/{}Names.txt'.format(keyword),mode='a',encoding='utf-8') as f:
for i in range(len(musicNames)):
f.writelines(musicNames[i]+"\n")
with open(file='D:/intell/Clock/src/file/{}hash.txt'.format(keyword),mode='a',encoding='utf-8') as f:
for i in range(len(hash_list)):
f.writelines(hash_list[i][0]+'\t'+hash_list[i][1]+"\n")
music.py
from sys import argv
import requests
import json
hash=argv[1]
id=argv[2]
keyword=argv[3]
if(id=="0"):
id=""
url='https://wwwapi.kugou.com/yy/index.php?r=play/getdata&hash=%s&album_id=%s&dfid=2SSV0x4LWcsx0iylej1F6w7P&mid=44328d3dc4bfce21cf2b95cf9e76b968&platid=4'
headers={
'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3756.400 QQBrowser/10.5.4039.400'}
url=url%(hash,id)
response=requests.get(url=url,headers=headers)
dict2=json.loads(response.text)
music_info=dict2['data']['lyrics'] # 歌曲信息
url2=dict2['data']['play_url']
with open(file="D:/intell/Clock/src/file2/{}.txt".format(keyword),mode="w",encoding="utf-8") as f:
f.write(music_info)
response2=requests.get(url=url2,headers=headers)
with open(file="D:/intell/Clock/src/file2/{}.mp3".format(keyword),mode="wb") as f:
f.write(response2.content)
print("1")
在2的时候讲了Java调用python,那么具体怎样调用呢?
看了这张图片,读者是不是发现这个和第1点的运行结果是不是很相似,当然这个的完成小编觉得应该要配置python环境变量的(不过,小编想读者都应该配置好了吧!)
当然了,读者还需要再src文件夹下面新建两个如下的文件夹,另外,读者运行一次这个程序之后,最好把文件夹file里面的文件全部删除,否则下次运行的时候会出一定错误,file2不需要任何操作。
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.URL;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import javax.sound.sampled.*;
public class music extends JFrame {
private JPanel topPanel;
private JPanel CenterPanel2;
private JPanel centerPanel;
private JPanel bottomPanel;
private JLabel label;
private JTextField textField;
private JButton button;
private DefaultListModel<String> listModel; // 列表框
private JList<String> jList;
private List<String> list;
private List<String> list2;
private Integer index=0;
private String hash; //歌曲的hash码
private String id; // 歌曲的id码
private String musicName; // 歌曲名
private Font font;
private JToolBar toolBar; //工具栏
private JButton ssButton;
private JButton bfButton;
private JButton zbButton;
private JPanel textPanel2;
private Integer num=0;
private List<String> music_words2;
private Timer timer;
private int num2=0;
private int num3=1;
private Integer time;
private JTextArea textArea;
private JLabel label2;
public music(){
super("某某音乐");
topPanel=new JPanel();
topPanel.setSize(1000,60);
label=new JLabel("歌曲名:");
topPanel.add(label,FlowLayout.LEFT);
font=new Font("华文宋体",Font.BOLD,20);
textField=new JTextField();
textField.setColumns(22);
textField.setFont(font);
topPanel.add(textField,FlowLayout.CENTER);
button=new JButton("搜索");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
String keyword=textField.getText();
write_file(keyword);
setList(list,keyword+"Names");
listModel.clear();
jList.repaint();
for(int i=0;i<list.size();i++)
listModel.insertElementAt(list.get(i),i);
jList.repaint();
centerPanel.repaint();
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
topPanel.add(button,FlowLayout.RIGHT);
CenterPanel2=new JPanel();
CenterPanel2.setSize(1000,700);
CardLayout cardLayout=new CardLayout();
CenterPanel2.setLayout(cardLayout);
centerPanel=new JPanel();
centerPanel.setSize(1000,700);
list=new LinkedList<>();
list2=new LinkedList<>();
listModel=new DefaultListModel<String>();
jList = new JList<String>(listModel);
jList.setFont(font);
jList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
jList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
setIndex(jList.getSelectedIndex());
setMusicName(jList.getSelectedValue());
}
});
JScrollPane scrollPane1 = new JScrollPane(jList);
scrollPane1.setPreferredSize(new Dimension(900, 700));
centerPanel.add(scrollPane1);
CenterPanel2.add(centerPanel,"0");
textArea=new JTextArea();
textArea.setSize(900,700);
textArea.setFont(font);
textArea.setEditable(false);
textPanel2=new JPanel();
textPanel2.add(textArea);
CenterPanel2.add(textPanel2,"1");
bottomPanel=new JPanel();
toolBar=new JToolBar(JToolBar.HORIZONTAL);
zbButton=new JButton(getImage("sx"));
zbButton.setToolTipText("转变");
zbButton.setFont(font);
zbButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(num==0){
cardLayout.show(CenterPanel2,"1");
num+=1;
}else{
cardLayout.show(CenterPanel2,"0");
num=0;
}
}
});
toolBar.add(zbButton);
ssButton=new JButton("缓冲");
ssButton.setFont(font);
music_words2=new LinkedList<String>();
ssButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
String keyword=textField.getText();
System.out.println(keyword);
setList(list2,keyword+"hash");
List<String> list3= Arrays.asList(list2.get(index).split("\t"));
try{
setHash(list3.get(0));
setId(list3.get(1));
}catch (Exception ex2){
setHash(list3.get(0));
setId("0");
}
download_file(hash,id,musicName);
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
toolBar.add(ssButton);
bfButton=new JButton(getImage("ss"));
bfButton.setToolTipText("播放");
bfButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
List<String> music_words=null;
try {
music_words = getMusicWord(musicName);
System.out.println(musicName);
} catch (Exception ex) {
ex.printStackTrace();
}
for(int i=0;i<music_words.size();i++){
if(!("".equals(music_words.get(i))))
music_words2.add(music_words.get(i));
}
List<List<String>> music_words3=new LinkedList<>();
for(int i=0;i<music_words2.size();i++){
String string=music_words2.get(i);
int index=string.indexOf("]")+1;
if(string.substring(index).length()!=0){
List<String> list4=new LinkedList<String>();
list4.add(string.substring(0,index));
list4.add(string.substring(index));
music_words3.add(list4);
}
}
int len=music_words3.size();
System.out.println(len);
label2.setText("音乐开始播放!");
textArea.setText("");
time=get_time("0",music_words3.get(0).get(0));
timer=new Timer(time, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(num2<28){
textArea.append(music_words3.get(num2++).get(1)+"\n");
textArea.repaint();
}else{
textArea.setText("");
for(int i=num3;i<num2;i++){
textArea.append(music_words3.get(i).get(1)+"\n");
}
textArea.append(music_words3.get(num2++).get(1)+"\n");
textArea.repaint();
num3++;
}
if(num2>0 &&num2!=len){
time=get_time(music_words3.get(num2-1).get(0),music_words3.get(num2).get(0));
System.out.println(time);
}
timer.setDelay(time); // 重新设置时间间隔
String string2=label2.getText();
if(num2%2==0)
label2.setText(string2+".");
if(num2==len){
label2.setText("音乐播放完毕!");
label2.repaint();
num2=0;
num3=1;
music_words2.clear();
timer.stop();
}
System.out.println("num2:"+num2);
}
});
Thread thread1=new Thread(new Runnable() {
@Override
public void run() {
timer.start();
}
});
Thread thread2=new Thread(new Runnable() {
@Override
public void run() {
play(musicName);
}
});
thread1.start();
thread2.start(); // 定义两个线程,让播放音乐和歌词同时执行
}
});
toolBar.add(bfButton);
label2=new JLabel("音乐");
Font font2=new Font("方正楷体",Font.BOLD,20);
label2.setFont(font2);
toolBar.add(label2);
bottomPanel.add(toolBar);
add(topPanel,BorderLayout.NORTH);
add(CenterPanel2,BorderLayout.CENTER);
add(bottomPanel,BorderLayout.SOUTH);
setBounds(200,200,1000,900);
setResizable(false); // 设置窗体大小为固定,不可放大
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void setIndex(Integer index) {
this.index = index;
}
public void setMusicName(String musicName) {
this.musicName = musicName;
}
public void setHash(String hash) {
this.hash = hash;
}
public void setId(String id) {
this.id = id;
}
public void setList(List<String> list, String keyword) throws Exception{
String filename=String.format("src/file/%s.txt",keyword);
File file=new File(filename);
if(list.size()>0){
list.clear();
}
if(file.exists()){
FileReader fr=new FileReader(filename);
BufferedReader bf=new BufferedReader(fr);
while(bf.ready()){
list.add(bf.readLine());
}
bf.close();
fr.close();
}
}// 得到歌曲列表
public List<String> getMusicWord(String keyword) throws Exception {
List<String> list1 = new LinkedList<String>();
String filename = String.format("src/file2/%s.txt", keyword);
File file = new File(filename);
if (file.exists()) {
FileReader fr = new FileReader(filename);
BufferedReader bf = new BufferedReader(fr);
while (bf.ready()) {
list1.add(bf.readLine());
}
bf.close();
fr.close();
}
return list1;
}
public ImageIcon getImage(String name){
URL url=getClass().getResource("/images/"+name+".jpg");
ImageIcon imageIcon=new ImageIcon(url);
return imageIcon;
}
public void write_file(String keyword) throws Exception {
if("".equals(keyword)){
keyword="夜航星";
}
String exe = "python";
String command = "D:\\Sublime\\PyCharm\\music\\music2.py";
String[] cmdArr = new String[] {
exe,command,keyword};
Process process = Runtime.getRuntime().exec(cmdArr);
process.waitFor();
}
public static Integer get_time(String time1,String time2){
int index1=time2.indexOf(":")+1;
int index2=time2.indexOf("]");
int index3=time2.indexOf("[")+1;
int time3;
if("0".equals(time1)){
time3=0;
}else{
time3=Integer.parseInt(time1.substring(index3,index1-1))*1000*60+(int) (Double.parseDouble(time1.substring(index1,index2))*1000);
}
int time4=Integer.parseInt(time2.substring(index3,index1-1))*1000*60+(int) (Double.parseDouble(time2.substring(index1,index2))*1000);
return time4-time3;
}
public static void play(String musicName){
String filePath=String.format("src/file2/%s.mp3",musicName);
try {
// 文件流
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File(filePath));
// 文件编码
AudioFormat audioFormat = audioInputStream.getFormat();
// 转换文件编码
if (audioFormat.getEncoding() != AudioFormat.Encoding.PCM_SIGNED) {
System.out.println(audioFormat.getEncoding());
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 = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
// 将数据行用指定的编码打开
sourceDataLine.open(audioFormat);
// 使数据行得到数据时就开始播放
sourceDataLine.start();
int bytesPerFrame = audioInputStream.getFormat().getFrameSize();
// 将流数据逐渐写入数据行,边写边播
int numBytes = 1024 * bytesPerFrame;
byte[] audioBytes = new byte[numBytes];
while (audioInputStream.read(audioBytes) != -1) {
sourceDataLine.write(audioBytes, 0, audioBytes.length);
}
sourceDataLine.drain();
sourceDataLine.stop();
sourceDataLine.close();
} catch (Exception e) {
e.printStackTrace();
}
}// 播放音乐代码
public void download_file(String hash,String id,String keyword) throws Exception{
String exe = "python";
String command = "D:\\Sublime\\PyCharm\\music\\music.py";
String[] comArr = new String[]{
exe, command, hash, id, keyword};
System.out.println(exe+" "+command+" "+hash+" "+id+" "+keyword);
Process process = Runtime.getRuntime().exec(comArr);
process.waitFor();
}
public static void main(String[] args) throws Exception {
new music().setVisible(true);
}
}
在这里小编讲明一点,代码中需要用到图片,所以读者最好在src文件夹下面新建一个images文件夹,然后在下面添加两张40*40像素的图片,图片命名分别为ss.jpg(播放图标)和sx.jpg(转变图标).如下:
另外,由于Java无法播放.mp3文件,所以小编在网上找了一些资料,终于有了一篇博客讲到了,博客链接为:利用JAVA SOUND播放mp3,flac,ape格式音乐,这篇博客讲到需要将几个.jar文件导入,小编用的IntelliJ IDEA,怎样导入呢?小编到网上找了一下,觉得这一篇博客不错,博客链接为:IntelliJ IDEA java项目导入jar包,打jar包
也许读者用的编辑器不同,希望到时候如果读者真的想实践一下,到网上找一下资料吧!
这个音乐播放软件比起用python实现效果好多了,真的,希望到时候读者觉得这个还不错的话!点赞一下呗!小编在此谢了!