Python----PyQt开发(PyQt高级:手搓一个音乐播放器)

news/2025/3/1 12:06:27/

一、效果展示

二、设计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)  # 初始化滑块值为0self.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)  # 初始化音量值为30self.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, QMediaContentclass 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)  # 初始化滑块值为0self.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)  # 初始化音量值为30self.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  # 如果索引超出范围,重置为0else: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_())  # 进入应用程序主循环


http://www.ppmy.cn/news/1575762.html

相关文章

Deepseek开源周第四天:从 DualPipe 到 EPLB

Deepseek开源周第四天&#xff1a;从 DualPipe 到 EPLB 前言 上周deepseek宣布&#xff0c;将在本周陆续发布五个开源项目&#xff0c;这些库已经在生产环境中经过了记录、部署和实战测试。 今天是deepseek开源周的第四天&#xff0c;deepseek发布了三个开源项目&#xff0c;…

网络安全清单

&#x1f345; 点击文末小卡片 &#xff0c;免费获取网络安全全套资料&#xff0c;资料在手&#xff0c;涨薪更快 移除(Deprovisioning) 移除&#xff08;Deprovisioning&#xff09;是一个除去现存用户帐户的过程&#xff0c;其包括用户帐户登记和设备失效。 分布式编码规则…

计算机毕业设计Python+DeepSeek-R1大模型期货价格预测分析 期货价格数据分析可视化预测系 统 量化交易大数据 机器学习 深度学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

【计网】物理层

物理层 2.1 物理层的基本概念2.2 物理层下面的传输媒体2.2.1 引导型2.2.2 非引导型 2.3 传输方式2.3.1 串行/并行2.3.2 同步/异步2.3.3 单工/半双工/全双工 2.4 编码与调制2.4.1 常用编码2.4.2 基本调制方法 2.5 信道的极限容量2.5.1 奈氏准则2.5.2 香农公式 2.1 物理层的基本概…

力扣 划分字母区间

贪心算法&#xff0c;存状态&#xff0c;合并区间。 题目 同一字母最多出现在一个片段中&#xff0c;因此要找到相同字母的上界跟下界。由于是对字符串进行划分&#xff0c;在一个片段内&#xff0c;从前往后遍历&#xff0c;找到每个字母的最后一个下标即是可能的划分点了&am…

Openharmony4.1版 SystemUI编译笔记

参考文献&#xff1a; 如何在OpenH​​​​​​rmony 4.1R上设置系统默认不锁屏(修改系统锁屏应用)_离北况归-Laval社区 环境配置 参考离北况归的文章&#xff0c;openharmony4.1r版本的系统应用需要使用4.1版本的DevecoStudio工具进行编译&#xff0c;高版本开发工具会编译…

【 实战案例篇三】【某金融信息系统项目管理案例分析】

大家好,今天咱们来聊聊金融行业的信息系统项目管理。这个话题听起来可能有点专业,但别担心,我会尽量用大白话给大家讲清楚。金融行业的信息系统项目管理,说白了就是如何高效地管理那些复杂的IT项目,确保它们按时、按预算、按质量完成。咱们今天不仅会聊到一些理论,还会通…

今日行情明日机会——20250227

明日短线投资方向分析 根据最新盘面数据&#xff0c;以下板块及个股具备短线机会&#xff0c;需结合开盘竞价与资金流向灵活应对&#xff1a; 1. 算力&#xff08;核心主线&#xff09; 核心逻辑&#xff1a;大位科技&#xff08;五板&#xff09;打开市场高度&#xff0c;广…