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

news/2025/2/23 17:50:35

一、效果展示

二、设计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_())  # 进入应用程序主循环


http://www.niftyadmin.cn/n/5863637.html

相关文章

uniapp 整合openlayers 编辑图形文件并上传到服务器

引入openlayer依赖 import Map from ol/Map.js // OpenLayers的主要类&#xff0c;用于创建和管理地图 import View from ol/View.js // OpenLayers的视图类&#xff0c;定义地图的视图属性 import TileLayer from ol/layer/Tile.js// OpenLayers的瓦片图层类 import…

verilog中等难度设计实践与ALU设计

Verilog中等难度部分设计实践&#xff08;含ALU算术逻辑单元的设计&#xff09; verilog的中等部分根据Deepseek给出的大纲理应包括时序逻辑verilog设计实践和组合逻辑verilog组合设计实践两个部分。 时序逻辑verilog设计和实践 在 Verilog 中&#xff0c;时序逻辑通常通过 …

计算机考研复试上机07

14、数据结构 1)二叉树 1.常用操作 struct TreeNode{int data;TreeNode *leftChild;TreeNode *rightChild; }; //前序遍历 void PreOrder(TreeNode *root){if(root == NULL) return;visit(root->data);PreOrder(root->leftChild);PreOrder(root->rightChild);ret…

提效10倍:基于Paimon+Dolphin湖仓一体新架构在阿里妈妈品牌业务探索实践

1. 业务背景 阿里妈妈品牌广告数据包括投放引擎、下发、曝光、点击等日志&#xff0c;面向运筹调控、算法特征、分析报表、诊断监控等应用场景&#xff0c;进行了品牌数仓能力建设。随着业务发展&#xff0c;基于Lambda架构的数仓开发模式&#xff0c;缺陷日益突出&#xff1a;…

Windows 上编译 mebedtls 的鸿蒙库

mebedtls 地址&#xff1a;https://github.com/Mbed-TLS/mbedtls 准备工作&#xff1a; clone mebedtls 仓库到本地(tag: mbedtls-2.26.0)鸿蒙工具链(SDK version: v5.0.5) 编译文件修改&#xff1a; 对 CMakeLists.txt 进行修改&#xff0c;主要是关闭了以下几个选项 ENABLE_P…

Spring Boot Validation 接口校验:从零到掌握

在开发 Web 应用时&#xff0c;数据校验是不可忽视的一部分。无论是注册用户信息、提交表单数据&#xff0c;还是处理业务逻辑&#xff0c;数据的有效性和完整性都需要得到保证。Spring Boot 提供了强大的验证功能&#xff0c;基于 Hibernate Validator 框架&#xff0c;通过注…

11.Docker 之分布式仓库 Harbor

Docker 之分布式仓库 Harbor Docker 之分布式仓库 Harbor1. Harbor 组成2. 安装 Harbor Docker 之分布式仓库 Harbor Harbor 是一个用于存储和分发 Docker 镜像的企业级 Registry 服务器&#xff0c;由 VMware 开源&#xff0c;其通过添加一些企业必需的功能特性&#xff0c;例…

Spring Boot 集成 T-io 实现客户端服务器通信

Spring Boot 集成 T-io 实现客户端服务器通信 本文详细介绍如何在 Spring Boot 项目中集成 T-io 框架&#xff0c;实现客户端与服务器之间的通信&#xff0c;并支持组聊、群聊和私聊功能。通过本文&#xff0c;您能够全面了解 T-io core 的使用方法&#xff0c;以及如何正确启…