一、效果展示
二、设计PyQt界面
本次ui界面设置用到了水平和垂直布局
2.1、设置ui窗口显示大小与位置
python"> self.setWindowTitle('音乐播放器') # 设置窗口标题
self.setGeometry(800, 300, 800, 800) # 设置窗口大小和位置
2.2、创建显示歌曲列表控件
python"> # 创建显示歌曲列表的控件
self.song_list = QListWidget(self)
2.3、创建歌曲名称和歌曲时间
python"> self.name_label = QLabel('歌曲名称', self)
self.time_label = QLabel('00:00/00:00', self)
2.4、把歌曲名称和歌曲时间水平布局
python"> # 创建水平布局用于放置歌曲名称和时间标签
self.label_layout = QHBoxLayout()
self.label_layout.addWidget(self.name_label)
self.label_layout.addWidget(self.time_label)
2.5、创建歌曲进度条
python"> # 创建播放进度滑块
self.player_slider = QSlider()
self.player_slider.setValue(0) # 初始化滑块值为0
self.player_slider.setOrientation(Qt.Horizontal) # 设置为水平滑块
2.6、创建播放,选择文件,上一首,下一首组件
python"> # 创建控制按钮
self.play_btn = QPushButton('播放', self)
self.choose_btn = QPushButton('选择文件', self)
self.pre_btn = QPushButton('上一首', self)
self.next_btn = QPushButton('下一首', self)
2.7、创建音量进度条
python"> # 创建音量滑块
self.volume_slider = QSlider()
self.volume_slider.setRange(0, 100) # 设置音量范围
self.volume_slider.setValue(30) # 初始化音量值为30
self.volume_slider.setOrientation(Qt.Horizontal) # 设置为水平滑块
2.8、将按钮组件和音量进度条放在同一水平布局
python"> # 创建按钮水平布局
self.btn_layout = QHBoxLayout()
self.btn_layout.addWidget(self.play_btn)
self.btn_layout.addWidget(self.choose_btn)
self.btn_layout.addWidget(self.pre_btn)
self.btn_layout.addWidget(self.next_btn)
self.btn_layout.addWidget(self.volume_slider)
2.9、创建垂直布局,将其组件放入
python"> # 创建主垂直布局
self.vbox = QVBoxLayout()
self.vbox.addWidget(self.song_list) # 添加歌曲列表
self.vbox.addLayout(self.label_layout) # 添加标签布局
self.vbox.addWidget(self.player_slider) # 添加播放进度滑块
self.vbox.addLayout(self.btn_layout) # 添加按钮布局
2.10、设置主布局
python"> self.setLayout(self.vbox) # 设置主布局
三、添加事件
3.1、设置按钮点击事件到对应的槽函数
python"> # 连接按钮点击事件到对应的槽函数
self.play_btn.clicked.connect(self.play_slot)
self.choose_btn.clicked.connect(self.choose_slot)
self.pre_btn.clicked.connect(self.previous_slot)
self.next_btn.clicked.connect(self.next_slot)
播放暂停
python"> def play_slot(self):
# 控制播放和暂停的逻辑
if self.play_btn.text() == '播放':
self.timer.start(1000) # 启动定时器,每秒更新一次
self.MP3_player.play() # 播放音乐
self.play_btn.setText('暂停') # 更新按钮文本
else:
self.timer.stop() # 停止定时器
self.MP3_player.pause() # 暂停音乐
self.play_btn.setText('播放') # 更新按钮文本
选择文件
python"> def choose_slot(self):
# 打开文件对话框选择音乐文件
self.music_path, _ = QFileDialog.getOpenFileName(self, '选择歌曲', './', 'MP3(*.mp3)')
if self.music_path: # 确保选择了文件
self.music_name = QFileInfo(self.music_path).fileName() # 获取文件名
self.song_list.addItem(QListWidgetItem(self.music_name)) # 将歌曲添加到列表
self.song_list_data.append(self.music_path) # 将路径存储到数据列表中
self.name_label.setText(self.music_name) # 更新当前歌曲名称
self.MP3_player.setMedia(QMediaContent(QUrl(self.music_path))) # 设置媒体内容
self.timer.start(1000) # 启动定时器
上一首
python"> def previous_slot(self):
# 播放上一首歌曲的逻辑
if self.song_list.currentRow() > 0: # 如果有上一首歌
self.song_list.setCurrentRow(self.song_list.currentRow() - 1) # 当前行减一
self.play_selected_song() # 播放选中的歌曲
下一首
python"> def next_slot(self):
# 播放下一首歌曲的逻辑
if self.song_list.currentRow() < self.song_list.count() - 1: # 如果有下一首歌
self.song_list.setCurrentRow(self.song_list.currentRow() + 1) # 当前行加一
self.play_selected_song() # 播放选中的歌曲
3.2、为滑块添加事件
播放进度滑块
python"> # 连接播放器状态变化信号到对应的槽函数
self.MP3_player.positionChanged.connect(self.update_playspider_value)
# 连接滑块移动事件到对应的槽函数
self.player_slider.sliderMoved.connect(self.update_player_position)
python"> def update_playspider_value(self, position):
# 更新播放进度滑块的值
self.player_slider.setValue(position)
python"> def update_player_position(self, position):
# 设置播放器的播放位置
self.MP3_player.setPosition(position)
音量滑块
python"> # 连接播放器状态变化信号到对应的槽函数
self.MP3_player.durationChanged.connect(self.update_player_volume)
# 连接滑块移动事件到对应的槽函数
self.volume_slider.sliderMoved.connect(self.update_volume_slot)
python"> def update_player_volume(self, duration):
# 更新音量滑块的范围,根据音频的时长设置滑块的范围
self.player_slider.setRange(0, duration)
python"> def update_volume_slot(self, position):
# 更新播放器音量
self.MP3_player.setVolume(position)
四、用到的库函数
Qt Widgets 和布局:
QWidget: 创建基本的窗口部件。
QPushButton: 创建按钮。
QListWidget: 创建一个列表控件,用于显示歌曲列表。
QLabel: 创建标签,用于显示文本。
QHBoxLayout: 创建水平布局管理器。
QVBoxLayout: 创建垂直布局管理器。
QSlider: 创建滑块控件,用于调节音量和播放进度。
Qt Multimedia:
QMediaPlayer: 媒体播放器类,用于播放音频文件。
QMediaContent: 媒体内容类,用于设置播放的音频文件。
Qt Core:
QUrl: 用于处理 URL。
QFileInfo: 用于获取文件的信息。
QTimer: 用于定时器功能。
QTime: 用于处理时间。
Qt: 包含常量和枚举,例如 Qt.Horizontal。
事件和信号槽:
clicked.connect(): 连接按钮点击事件到槽函数。
positionChanged.connect(): 连接播放器位置变化信号到槽函数。
durationChanged.connect(): 连接播放器时长变化信号到槽函数。
sliderMoved.connect(): 连接滑块移动事件到槽函数。
文件对话框:
QFileDialog.getOpenFileName(): 打开文件对话框以选择文件。
其他:
setText(): 设置标签的文本。
setCurrentRow(): 设置当前选中的行。
addItem(): 向列表控件中添加项目。
setMedia(): 设置媒体内容。
play(): 播放音频。
pause(): 暂停音频。
stop(): 停止音频。
setVolume(): 设置播放器音量。
setPosition(): 设置播放器播放位置。
setRange(): 设置滑块的范围。
setValue(): 设置滑块的值。
五、完整代码
python">import sys
from PyQt5.QtCore import QUrl, QFileInfo, QTimer, QTime
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QListWidget, QLabel, QHBoxLayout, QVBoxLayout, QSlider, \
QFileDialog, QListWidgetItem
from PyQt5.QtCore import Qt
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
class AudioWidge(QWidget):
def __init__(self):
super().__init__()
self.ui_init()
self.songname_index = 0 # 用于歌曲名称显示的索引
self.song_list_data = [] # 存储歌曲列表的数据
self.slot_init()
def ui_init(self):
self.MP3_player = QMediaPlayer() # 创建媒体播放器对象
self.setWindowTitle('音乐播放器') # 设置窗口标题
self.setGeometry(800, 300, 800, 800) # 设置窗口大小和位置
# 创建显示歌曲列表的控件
self.song_list = QListWidget(self)
# 创建显示当前歌曲名称和播放时间的标签
self.name_label = QLabel('歌曲名称', self)
self.time_label = QLabel('00:00/00:00', self)
# 创建水平布局用于放置歌曲名称和时间标签
self.label_layout = QHBoxLayout()
self.label_layout.addWidget(self.name_label)
self.label_layout.addWidget(self.time_label)
# 创建播放进度滑块
self.player_slider = QSlider()
self.player_slider.setValue(0) # 初始化滑块值为0
self.player_slider.setOrientation(Qt.Horizontal) # 设置为水平滑块
# 创建控制按钮
self.play_btn = QPushButton('播放', self)
self.choose_btn = QPushButton('选择文件', self)
self.pre_btn = QPushButton('上一首', self)
self.next_btn = QPushButton('下一首', self)
# 创建音量滑块
self.volume_slider = QSlider()
self.volume_slider.setRange(0, 100) # 设置音量范围
self.volume_slider.setValue(30) # 初始化音量值为30
self.volume_slider.setOrientation(Qt.Horizontal) # 设置为水平滑块
# 创建按钮水平布局
self.btn_layout = QHBoxLayout()
self.btn_layout.addWidget(self.play_btn)
self.btn_layout.addWidget(self.choose_btn)
self.btn_layout.addWidget(self.pre_btn)
self.btn_layout.addWidget(self.next_btn)
self.btn_layout.addWidget(self.volume_slider)
# 创建主垂直布局
self.vbox = QVBoxLayout()
self.vbox.addWidget(self.song_list) # 添加歌曲列表
self.vbox.addLayout(self.label_layout) # 添加标签布局
self.vbox.addWidget(self.player_slider) # 添加播放进度滑块
self.vbox.addLayout(self.btn_layout) # 添加按钮布局
self.setLayout(self.vbox) # 设置主布局
def slot_init(self):
# 连接按钮点击事件到对应的槽函数
self.play_btn.clicked.connect(self.play_slot)
self.choose_btn.clicked.connect(self.choose_slot)
self.pre_btn.clicked.connect(self.previous_slot)
self.next_btn.clicked.connect(self.next_slot)
# 连接播放器状态变化信号到对应的槽函数
self.MP3_player.positionChanged.connect(self.update_playspider_value)
self.MP3_player.durationChanged.connect(self.update_player_volume)
# 连接滑块移动事件到对应的槽函数
self.player_slider.sliderMoved.connect(self.update_player_position)
self.volume_slider.sliderMoved.connect(self.update_volume_slot)
# 初始化定时器,用于更新播放时间
self.timer = QTimer(self)
self.timer.timeout.connect(self.update_time_slot)
def play_slot(self):
# 控制播放和暂停的逻辑
if self.play_btn.text() == '播放':
self.timer.start(1000) # 启动定时器,每秒更新一次
self.MP3_player.play() # 播放音乐
self.play_btn.setText('暂停') # 更新按钮文本
else:
self.timer.stop() # 停止定时器
self.MP3_player.pause() # 暂停音乐
self.play_btn.setText('播放') # 更新按钮文本
def choose_slot(self):
# 打开文件对话框选择音乐文件
self.music_path, _ = QFileDialog.getOpenFileName(self, '选择歌曲', './', 'MP3(*.mp3)')
if self.music_path: # 确保选择了文件
self.music_name = QFileInfo(self.music_path).fileName() # 获取文件名
self.song_list.addItem(QListWidgetItem(self.music_name)) # 将歌曲添加到列表
self.song_list_data.append(self.music_path) # 将路径存储到数据列表中
self.name_label.setText(self.music_name) # 更新当前歌曲名称
self.MP3_player.setMedia(QMediaContent(QUrl(self.music_path))) # 设置媒体内容
self.timer.start(1000) # 启动定时器
def previous_slot(self):
# 播放上一首歌曲的逻辑
if self.song_list.currentRow() > 0: # 如果有上一首歌
self.song_list.setCurrentRow(self.song_list.currentRow() - 1) # 当前行减一
self.play_selected_song() # 播放选中的歌曲
def next_slot(self):
# 播放下一首歌曲的逻辑
if self.song_list.currentRow() < self.song_list.count() - 1: # 如果有下一首歌
self.song_list.setCurrentRow(self.song_list.currentRow() + 1) # 当前行加一
self.play_selected_song() # 播放选中的歌曲
def play_selected_song(self):
# 播放当前选中的歌曲
current_row = self.song_list.currentRow()
if current_row >= 0 and current_row < len(self.song_list_data): # 确保索引在有效范围内
self.music_path = self.song_list_data[current_row] # 获取当前歌曲文件路径
self.music_name = QFileInfo(self.music_path).fileName() # 获取文件名
self.name_label.setText(self.music_name) # 更新当前歌曲名称
self.MP3_player.setMedia(QMediaContent(QUrl(self.music_path))) # 设置媒体内容
self.MP3_player.play() # 播放音乐
def timerEvent(self, a0):
# 处理定时器事件,用于更新歌曲名称显示
if self.songname_index == len(self.music_name):
self.songname_index = 0 # 如果索引超出范围,重置为0
else:
self.songname_index += 1 # 增加索引
self.name_label.setText(self.music_name[self.songname_index:]) # 更新歌曲名称显示
def update_time_slot(self):
# 更新播放时间和总时长显示
cur_playtime = self.MP3_player.position() # 获取当前播放时长
music_time = self.MP3_player.duration() # 获取音乐总时长
# 格式化当前播放时长和总时长为 mm:ss 格式
cur_playtime_str = QTime(0, 0, 0, 0).addMSecs(cur_playtime).toString('mm:ss')
music_time_str = QTime(0, 0, 0, 0).addMSecs(music_time).toString('mm:ss')
# 更新时间标签显示
self.time_label.setText(cur_playtime_str + '/' + music_time_str)
def update_playspider_value(self, position):
# 更新播放进度滑块的值
self.player_slider.setValue(position)
def update_player_volume(self, duration):
# 更新音量滑块的范围,根据音频的时长设置滑块的范围
self.player_slider.setRange(0, duration)
def update_player_position(self, position):
# 设置播放器的播放位置
self.MP3_player.setPosition(position)
def update_volume_slot(self, position):
# 更新播放器音量
self.MP3_player.setVolume(position)
if __name__ == '__main__':
app = QApplication(sys.argv) # 创建应用程序
windows = AudioWidge() # 创建音乐播放器窗口
windows.show() # 显示窗口
sys.exit(app.exec_()) # 进入应用程序主循环