具体效果如下
需要实现的功能主要的几个有:
1、搜索结果更新至当前音乐的列表,这样播放下一首是搜素结果的下一首
2、自动播放
3、滚动音乐文本
4、音乐进度条
5、根据实际情况生成音乐列表。我这里的是下面的情况,音乐文件的格式是
歌名_歌手.mp3
所以根据需求修改 find_mp3_files 方法,我这里返回的是
[ {"path":音乐文件路径,
"music":歌名,
"singer":歌手},
{"path":音乐文件路径,
"music":歌名,
"singer":歌手},
...]
全部代码在此,试试吧
import fnmatch
import os
import random
import sysfrom PyQt5.QtGui import QPalette, QBrush, QPixmap
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QSlider, QLabel, \QTableWidget, QLineEdit, QTableWidgetItem
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
from PyQt5.QtCore import QUrl, Qt, QTimerclass MusicPlayer(QMainWindow):def __init__(self):super().__init__()self.music_path = "F://wyy" # 音乐文件夹,可以有子文件夹self.start_x = 10self.x_step = 100self.start_y = 10self.y_step = 40self.window_w, self.window_h = 500, 800self.music_list = self.find_mp3_files()self.show_list = self.music_listself.duration = 1self.position = 0self.text = "歌曲未加载"self.current_index = -1self.current_music = self.show_list[self.current_index]['music']self.current_singer = self.show_list[self.current_index]['singer']self.current_path = self.show_list[self.current_index]['path']self.status = Trueself.update_label = Trueself.init_ui()print("配置加载完成")def init_ui(self):self.setWindowTitle("音乐播放器")self.resize(self.window_w, self.window_h)self.setMinimumSize(self.window_w, self.window_h)self.setMaximumSize(self.window_w, self.window_h)palette = QPalette() # 主界面背景palette.setBrush(QPalette.Background, QBrush(QPixmap("imgs/21.jpg")))self.setPalette(palette)self.player = QMediaPlayer()self.table_widget = QTableWidget(0, 2, parent=self) # 检测结果列表self.table_widget.setHorizontalHeaderLabels(['歌手', '歌曲']) # 设置列表头self.table_widget.verticalHeader().hide() # 隐藏行索引self.table_widget.move(10, 150)self.table_widget.resize(500, 600)self.table_widget.cellClicked.connect(self.line_clicked)self.table_widget.setColumnWidth(0, 200)self.table_widget.setColumnWidth(1, 270)self.table_widget.setEditTriggers(QTableWidget.NoEditTriggers)self.table_widget.setStyleSheet("QTableWidget {background-image: url('imgs/11.jpg');}")self.load_music()self.play_button = QPushButton("播放", self)self.play_button.clicked.connect(self.play_current_music)self.play_button.move(self.start_x, self.start_y)self.change_button = QPushButton("暂停", self)self.change_button.clicked.connect(self.change_music_status)self.change_button.move(self.start_x + self.x_step, self.start_y)self.play_pre_button = QPushButton("上一首", self)self.play_pre_button.clicked.connect(self.play_pre)self.play_pre_button.move(self.start_x, self.start_y + self.y_step)self.play_next_button = QPushButton("下一首", self)self.play_next_button.clicked.connect(self.play_next)self.play_next_button.move(self.start_x + self.x_step, self.start_y + self.y_step)self.search_text = QLineEdit(self)self.search_text.resize(200, 30)self.search_text.move(self.start_x + 3 * self.x_step + 10, self.start_y)self.search_btn = QPushButton("搜索", self)self.search_btn.clicked.connect(self.search_music)self.search_btn.move(self.start_x + 2 * self.x_step + 10, self.start_y)self.music_label = QLabel(self.text, self)self.music_label.resize(self.window_w - self.start_x, 30)self.music_label.move(self.start_x, self.start_y + 2 * self.y_step)self.music_label.setAlignment(Qt.AlignCenter)self.volume_slider = QSlider(Qt.Horizontal, self)self.volume_slider.setRange(0, 100)self.volume_slider.setValue(50)self.volume_slider.setTickPosition(QSlider.TicksBelow)self.volume_slider.setTickInterval(10)self.volume_slider.resize(200, 30)self.volume_slider.valueChanged.connect(self.change_volume)self.volume_slider.move(self.start_x + 2 * self.x_step + 50, self.start_y + self.y_step + 10)self.music_pro = QLabel(self)self.music_pro_width = self.window_w - self.start_xself.music_pro.resize(self.music_pro_width, 10)self.music_pro.move(self.start_x, self.start_y + 2 * self.y_step + 40)self.music_pro.setStyleSheet("background:'#123456'")self.timer = QTimer()self.timer.timeout.connect(self.scroll_text)self.timer.start(500)self.player.stateChanged.connect(self.handle_player_status_changed)self.player.mediaStatusChanged.connect(self.handle_media_status_changed)self.player.durationChanged.connect(self.update_duration)self.player.positionChanged.connect(self.update_position)def change_music_status(self):if self.status:self.player.pause()self.status = Falseself.change_button.setText('继续')print("已暂停当前音乐", self.current_music)else:self.status = Trueself.player.play()self.change_button.setText('暂停')print("已继续当前音乐", self.current_music)def handle_media_status_changed(self, status):if status == QMediaPlayer.EndOfMedia:self.play_next()def handle_player_status_changed(self, state):if state == QMediaPlayer.PlayingState:self.update_label = Trueelif state == QMediaPlayer.StoppedState:self.update_label = Falsedef search_music(self):text = self.search_text.text()if text:self.show_list = []for i in self.music_list:for j in i.values():if text in j:self.show_list.append(i)breakself.load_music()print("查询结束")else:self.music_list = self.find_mp3_files() # 从本地重新加载self.show_list = self.music_list self.load_music()print('>>>>>>>>>>>>>>>未查询到相关音乐,已重新加载列表')def clear_table(self):self.table_widget.clearContents()self.table_widget.setHorizontalHeaderLabels(['歌手', '歌曲']) # 设置列表头self.table_widget.setRowCount(0)print("已更新列表")def line_clicked(self, row, column):self.current_index = rowself.update_current_music()print("点击了", self.current_music, self.current_singer)def load_music(self):self.clear_table()n = 0for i in self.show_list:self.table_widget.setRowCount(n + 1)self.table_widget.setItem(n, 0, QTableWidgetItem(i['singer']))self.table_widget.setItem(n, 1, QTableWidgetItem(i['music']))n += 1print('已重新加载音乐列表')def play_current_music(self):if self.current_index == -1:self.current_index = 0self.update_current_music()print(self.current_index)self.play_music()def play_music(self):self.player.setMedia(QMediaContent(QUrl.fromLocalFile(self.current_path)))self.player.play()self.text = f"当前播放: {self.current_music} —— {self.current_singer} "self.music_label.setText(self.text)print("正在播放:", self.current_music)def update_current_music(self):self.current_path = self.show_list[self.current_index]['path']self.current_singer = self.show_list[self.current_index]['singer']self.current_music = self.show_list[self.current_index]['music']print("已更新当前音乐")def play_pre(self):print("播放上一首")for i, j in enumerate(self.show_list):if self.current_path == j['path']:if i != 0:self.current_index = i - 1else:self.current_index = -1breakself.update_current_music()print("切换音乐为", self.current_music)self.play_music()def play_next(self):print("播放下一首")for i, j in enumerate(self.show_list):if self.current_path == j['path']:if i != len(self.show_list) - 1:self.current_index = i + 1else:self.current_index = 0breakself.update_current_music()print("切换音乐为", self.current_music)self.play_music()def change_volume(self, value):self.player.setVolume(value)print("设置音量为", value)def set_position(self):self.music_pro.resize(int(self.position / self.duration * self.music_pro_width), 10)c = int(self.position / self.duration * 255)h = self.rgb2hex(c, c, c)self.music_pro.setStyleSheet(f"background:'{h}'")def update_duration(self, duration):if not self.update_label:returnself.duration = durationdef update_position(self, position):if not self.update_label:returnself.position = positionself.set_position()def scroll_text(self):current_text = self.music_label.text()scroll_text = current_text[1:] + current_text[0]self.music_label.setText(scroll_text)self.music_label.setStyleSheet(f"color:{self.rgb2hex(*self.random_color())}")def rgb2hex(self, r, g, b):return "#{:02x}{:02x}{:02x}".format(r, g, b)def find_mp3_files(self): # 生成音乐文件列表,根据需求自定义mp3_files = []for root, dirs, files in os.walk(self.music_path):for file in files:if fnmatch.fnmatch(file, '*.mp3'):if '_' in file:r = {'music': file.split('_')[0],'singer': file.split('_')[1].split('.')[0],'path': os.path.join(root, file)}mp3_files.append(r)return mp3_filesdef random_color(self): # 随机颜色r, g, b = random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)return r, g, bif __name__ == "__main__":app = QApplication(sys.argv)player = MusicPlayer()player.show()sys.exit(app.exec_())