当前位置: 首页 > article >正文

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

一、效果展示

二、设计PyQt界面

本次ui界面设置用到了水平和垂直布局

2.1、设置ui窗口显示大小与位置

        self.setWindowTitle('音乐播放器')  # 设置窗口标题
        self.setGeometry(800, 300, 800, 800)  # 设置窗口大小和位置

2.2、创建显示歌曲列表控件

        # 创建显示歌曲列表的控件        
        self.song_list = QListWidget(self)

2.3、创建歌曲名称和歌曲时间

        self.name_label = QLabel('歌曲名称', self)
        self.time_label = QLabel('00:00/00:00', self)

2.4、把歌曲名称和歌曲时间水平布局

        # 创建水平布局用于放置歌曲名称和时间标签
        self.label_layout = QHBoxLayout()
        self.label_layout.addWidget(self.name_label)
        self.label_layout.addWidget(self.time_label)

2.5、创建歌曲进度条

        # 创建播放进度滑块
        self.player_slider = QSlider()
        self.player_slider.setValue(0)  # 初始化滑块值为0
        self.player_slider.setOrientation(Qt.Horizontal)  # 设置为水平滑块

2.6、创建播放,选择文件,上一首,下一首组件

        # 创建控制按钮
        self.play_btn = QPushButton('播放', self)
        self.choose_btn = QPushButton('选择文件', self)
        self.pre_btn = QPushButton('上一首', self)
        self.next_btn = QPushButton('下一首', self)

2.7、创建音量进度条

        # 创建音量滑块
        self.volume_slider = QSlider()
        self.volume_slider.setRange(0, 100)  # 设置音量范围
        self.volume_slider.setValue(30)  # 初始化音量值为30
        self.volume_slider.setOrientation(Qt.Horizontal)  # 设置为水平滑块

2.8、将按钮组件和音量进度条放在同一水平布局

        # 创建按钮水平布局
        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、创建垂直布局,将其组件放入

        # 创建主垂直布局
        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、设置主布局

        self.setLayout(self.vbox)  # 设置主布局

三、添加事件

3.1、设置按钮点击事件到对应的槽函数

        # 连接按钮点击事件到对应的槽函数
        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)

 播放暂停

    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()  # 播放选中的歌曲

3.2、为滑块添加事件

播放进度滑块

        # 连接播放器状态变化信号到对应的槽函数
        self.MP3_player.positionChanged.connect(self.update_playspider_value)
        # 连接滑块移动事件到对应的槽函数
        self.player_slider.sliderMoved.connect(self.update_player_position)
    def update_playspider_value(self, position):
        # 更新播放进度滑块的值
        self.player_slider.setValue(position)
    def update_player_position(self, position):
        # 设置播放器的播放位置
        self.MP3_player.setPosition(position)

音量滑块

        # 连接播放器状态变化信号到对应的槽函数
        self.MP3_player.durationChanged.connect(self.update_player_volume)
        # 连接滑块移动事件到对应的槽函数
        self.volume_slider.sliderMoved.connect(self.update_volume_slot)
    def update_player_volume(self, duration):
        # 更新音量滑块的范围,根据音频的时长设置滑块的范围
        self.player_slider.setRange(0, duration)
    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(): 设置滑块的值。

五、完整代码

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.kler.cn/a/559878.html

相关文章:

  • 《论多源数据集成及应用》审题技巧 - 系统架构设计师
  • 【报错解决】vue打开界面报错Uncaught SecurityError: Failed to construct ‘WebSocket‘
  • Leetcode2209:用地毯覆盖后的最少白色砖块
  • 谷粒商城学习笔记-13-配置git-ssh-配置代码免密提交
  • 【JavaEE进阶】Spring MVC(2)
  • 从 JS 到 Dart:语法基础
  • DNS实验(ENSP模拟器实现)
  • 什么AGI
  • 软件工程中涉及的多种图表
  • 关于在mac中配置Java系统环境变量
  • 美颜相机1.0
  • Go语言--语法基础1
  • 数据结构与算法设计-作业4-excel表合并与数据整理
  • Go 语言中的协程
  • 【GESP】C++二级真题 luogu-b3865, [GESP202309 二级] 小杨的 X 字矩阵
  • C++算法基础笔记
  • 2025-spring boot 之多数据源管理
  • 未授权理论知识记录
  • 【Web前端开发精品课 HTML CSS JavaScript基础教程】第二十六章课后题答案
  • 爬虫与反爬-Ja3指纹风控(Just a moment...)处理方案及参数说明