PYcharm——pyqt音乐播放器
系统概述
使用python开发一个简单的音乐播放器,如果你也无聊不妨动手试一下。
建一个基于 PyQt 的音乐播放器,实现图片中展示的功能,包括播放控制、进度条、音量调节、播放列表等核心功能。
我们将使用 PyQt5 作为 GUI 框架,结合 PyQt5 的 QMediaPlayer 组件来实现音频播放功能。
这个音乐播放器实现了以下功能:
核心播放控制:播放、暂停、停止、上一首、下一首
进度条显示和控制:可以拖动进度条调整播放位置
音量调节功能
播放列表管理:添加音乐、删除音乐、清空列表
歌曲信息显示:当前播放歌曲名、播放时间
右键菜单支持:对播放列表项进行操作
使用方法:
点击 “添加音乐” 按钮选择本地音频文件(支持 mp3、wav、flac、m4a 等格式)
在播放列表中双击歌曲开始播放
使用控制按钮进行播放控制
可以拖动进度条调整播放位置
使用音量滑块调节音量大小
要在 PyCharm 中运行此程序,你需要先安装 PyQt5 和 PyQt5 多媒体模块:
程序已经设置了中文字体支持,可以正常显示中文。界面布局简洁直观,符合图片中展示的音乐播放器基本功能需求。你可以根据需要进一步美化界面或添加更多功能,如均衡器、歌词显示等。
软件介绍
import sys
import os
from PyQt5.QtWidgets import (QApplication, QMainWindow, QPushButton, QSlider, QLabel, QListWidget, QFileDialog, QVBoxLayout, QHBoxLayout, QWidget, QStyle, QListWidgetItem,QSplitter, QMenu, QAction, QMessageBox)
from PyQt5.QtCore import Qt, QUrl, QTimer, QPoint
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
from PyQt5.QtGui import QIcon, QPixmap, QFontclass MusicPlayer(QMainWindow):def __init__(self):super().__init__()# 设置中文字体支持font = QFont()font.setFamily("SimHei")self.setFont(font)# 初始化媒体播放器self.player = QMediaPlayer()self.player.durationChanged.connect(self.update_duration)self.player.positionChanged.connect(self.update_position)self.player.stateChanged.connect(self.update_state)# 当前播放列表索引self.current_index = -1self.playlist = []# 初始化UIself.init_ui()def init_ui(self):# 设置窗口标题和大小self.setWindowTitle("音乐播放器")self.setGeometry(300, 300, 800, 600)# 创建中心部件central_widget = QWidget()self.setCentralWidget(central_widget)# 主布局main_layout = QVBoxLayout(central_widget)# 专辑封面self.album_cover = QLabel()self.album_cover.setAlignment(Qt.AlignCenter)self.album_cover.setMinimumHeight(300)# 设置默认封面default_pixmap = QPixmap(300, 300)default_pixmap.fill(Qt.lightGray)self.album_cover.setPixmap(default_pixmap.scaled(self.album_cover.width(), self.album_cover.height(), Qt.KeepAspectRatio, Qt.SmoothTransformation))main_layout.addWidget(self.album_cover)# 歌曲信息self.song_info = QLabel("准备就绪")self.song_info.setAlignment(Qt.AlignCenter)self.song_info.setStyleSheet("font-size: 16px; font-weight: bold;")main_layout.addWidget(self.song_info)# 进度条self.progress_layout = QHBoxLayout()self.time_label = QLabel("00:00")self.progress_layout.addWidget(self.time_label)self.progress_bar = QSlider(Qt.Horizontal)self.progress_bar.sliderMoved.connect(self.set_position)self.progress_layout.addWidget(self.progress_bar)self.total_time_label = QLabel("00:00")self.progress_layout.addWidget(self.total_time_label)main_layout.addLayout(self.progress_layout)# 控制按钮self.controls_layout = QHBoxLayout()self.prev_button = QPushButton()self.prev_button.setIcon(self.style().standardIcon(QStyle.SP_MediaSkipBackward))self.prev_button.clicked.connect(self.play_previous)self.controls_layout.addWidget(self.prev_button)self.play_button = QPushButton()self.play_button.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))self.play_button.clicked.connect(self.toggle_play_pause)self.controls_layout.addWidget(self.play_button)self.stop_button = QPushButton()self.stop_button.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))self.stop_button.clicked.connect(self.stop)self.controls_layout.addWidget(self.stop_button)self.next_button = QPushButton()self.next_button.setIcon(self.style().standardIcon(QStyle.SP_MediaSkipForward))self.next_button.clicked.connect(self.play_next)self.controls_layout.addWidget(self.next_button)self.controls_layout.addSpacing(20)# 音量控制self.volume_label = QLabel("音量:")self.controls_layout.addWidget(self.volume_label)self.volume_slider = QSlider(Qt.Horizontal)self.volume_slider.setMaximumWidth(100)self.volume_slider.setValue(70)self.player.setVolume(70)self.volume_slider.valueChanged.connect(self.set_volume)self.controls_layout.addWidget(self.volume_slider)main_layout.addLayout(self.controls_layout)# 分割器splitter = QSplitter(Qt.Vertical)# 播放列表self.playlist_label = QLabel("播放列表")self.playlist_label.setStyleSheet("font-size: 14px; font-weight: bold;")main_layout.addWidget(self.playlist_label)self.playlist_widget = QListWidget()self.playlist_widget.doubleClicked.connect(self.play_selected)# 右键菜单支持self.playlist_widget.setContextMenuPolicy(Qt.CustomContextMenu)self.playlist_widget.customContextMenuRequested.connect(self.show_context_menu)main_layout.addWidget(self.playlist_widget)# 底部按钮self.bottom_layout = QHBoxLayout()self.add_button = QPushButton("添加音乐")self.add_button.clicked.connect(self.add_music)self.bottom_layout.addWidget(self.add_button)self.clear_button = QPushButton("清空列表")self.clear_button.clicked.connect(self.clear_playlist)self.bottom_layout.addWidget(self.clear_button)main_layout.addLayout(self.bottom_layout)# 状态栏显示当前状态self.statusBar().showMessage("就绪")# 显示窗口self.show()def add_music(self):"""添加音乐到播放列表"""files, _ = QFileDialog.getOpenFileNames(self, "选择音乐文件", "", "音频文件 (*.mp3 *.wav *.flac *.m4a)")if files:for file in files:# 确保文件路径正确file_url = QUrl.fromLocalFile(file)# 获取文件名file_name = os.path.basename(file)# 添加到播放列表self.playlist.append((file_name, file_url))# 添加到列表控件self.playlist_widget.addItem(file_name)self.statusBar().showMessage(f"已添加 {len(files)} 首音乐")# 如果是第一个添加的音乐,自动选中if len(self.playlist) == len(files):self.playlist_widget.setCurrentRow(0)self.current_index = 0def play_selected(self):"""播放选中的音乐"""selected_index = self.playlist_widget.currentRow()if selected_index >= 0 and selected_index < len(self.playlist):self.current_index = selected_indexself.play_current()def play_current(self):"""播放当前索引的音乐"""if 0 <= self.current_index < len(self.playlist):song_name, url = self.playlist[self.current_index]self.player.setMedia(QMediaContent(url))self.player.play()self.song_info.setText(f"正在播放: {song_name}")self.statusBar().showMessage(f"正在播放: {song_name}")def toggle_play_pause(self):"""切换播放/暂停状态"""if self.player.state() == QMediaPlayer.PlayingState:self.player.pause()else:if self.player.mediaStatus() == QMediaPlayer.NoMedia and len(self.playlist) > 0:self.current_index = 0self.play_current()else:self.player.play()def stop(self):"""停止播放"""self.player.stop()self.song_info.setText("已停止")self.statusBar().showMessage("已停止")def play_next(self):"""播放下一首"""if len(self.playlist) == 0:returnself.current_index = (self.current_index + 1) % len(self.playlist)self.playlist_widget.setCurrentRow(self.current_index)self.play_current()def play_previous(self):"""播放上一首"""if len(self.playlist) == 0:returnself.current_index = (self.current_index - 1) % len(self.playlist)self.playlist_widget.setCurrentRow(self.current_index)self.play_current()def set_volume(self, value):"""设置音量"""self.player.setVolume(value)self.statusBar().showMessage(f"音量: {value}%")def update_duration(self, duration):"""更新总时长显示"""self.progress_bar.setRange(0, duration)# 转换为分:秒格式total_seconds = duration // 1000minutes = total_seconds // 60seconds = total_seconds % 60self.total_time_label.setText(f"{minutes:02d}:{seconds:02d}")def update_position(self, position):"""更新当前播放位置"""# 防止进度条更新时触发sliderMoved事件self.progress_bar.blockSignals(True)self.progress_bar.setValue(position)self.progress_bar.blockSignals(False)# 更新当前时间标签current_seconds = position // 1000minutes = current_seconds // 60seconds = current_seconds % 60self.time_label.setText(f"{minutes:02d}:{seconds:02d}")# 如果播放结束,自动播放下一首if position >= self.player.duration() and self.player.duration() > 0:self.play_next()def set_position(self, position):"""设置播放位置"""self.player.setPosition(position)def update_state(self, state):"""更新播放状态"""if state == QMediaPlayer.PlayingState:self.play_button.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))else:self.play_button.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))def clear_playlist(self):"""清空播放列表"""self.stop()self.playlist.clear()self.playlist_widget.clear()self.current_index = -1self.song_info.setText("播放列表已清空")self.statusBar().showMessage("播放列表已清空")def show_context_menu(self, position):"""显示右键菜单"""if not self.playlist_widget.selectedItems():returnmenu = QMenu()remove_action = QAction("移除选中项", self)remove_action.triggered.connect(self.remove_selected)play_action = QAction("播放选中项", self)play_action.triggered.connect(self.play_selected)menu.addAction(play_action)menu.addAction(remove_action)menu.exec_(self.playlist_widget.mapToGlobal(position))def remove_selected(self):"""移除选中的项目"""selected_items = self.playlist_widget.selectedItems()if not selected_items:return# 获取选中项的索引indexes = [self.playlist_widget.row(item) for item in selected_items]# 按降序排序,从后往前删除indexes.sort(reverse=True)for index in indexes:# 如果删除的是当前播放的歌曲if index == self.current_index:self.stop()# 如果不是最后一首歌,播放下一首if index < len(self.playlist) - 1:self.current_index = indexelse:self.current_index = 0 if len(self.playlist) > 1 else -1# 从列表中删除del self.playlist[index]# 从控件中删除item = self.playlist_widget.takeItem(index)del item# 更新当前索引(如果删除了前面的项目)if self.current_index > 0 and self.current_index >= len(self.playlist):self.current_index = len(self.playlist) - 1self.statusBar().showMessage(f"已移除 {len(selected_items)} 首音乐")if __name__ == "__main__":# 确保中文显示正常font = QFont("SimHei")app = QApplication(sys.argv)app.setFont(font)player = MusicPlayer()sys.exit(app.exec_())