使用PyQt5/PySide2编写一个极简的音乐播放器_pyside 音频_zmister2016的博客-程序员秘密

技术标签: python  图形界面实战  pyqt  gui  

疫情肆虐,憋在家实在无聊,索性写点东西,于是就有了这个极极极极极简的音乐播放器。

在这里插入图片描述
这个极极极简的音乐播放器类似于“阅后即焚”的软件,播放器可以随机播放歌曲,获取下一首歌曲,不能重新播放上一首歌曲,不能获取歌曲的名称和演唱者。听过的歌曲,就像过眼云烟,放完即散。

下面来看看如何用Python实现这个音乐播放器软件吧!

一、创建UI界面

首先,我们来创建这个播放器的UI界面。这个播放器一共有6个控件:

  • 左上角的程序关闭按钮;
  • 左侧的播放状态标签;
  • 顶部的slogan;
  • 播放/暂停按钮;
  • 下一首按钮;
  • 播放进度条;

基于以上控件,我们用一个网格布局来排列:

class Music(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.setFixedSize(400,200)
        self.setWindowTitle("州的先生")
        self.init_ui()
        self.custom_style()
        self.playing = False # 播放状态初始化为否
        self.player = QMediaPlayer(self)

    # 设置样式
    def custom_style(self):
        self.setStyleSheet('''
            #main_widget{
                border-radius:5px;
            }
            #play_btn,#pervious_btn,#next_btn{
                border:none;
            }
            #play_btn:hover,#pervious_btn:hover,#next_btn:hover{
                background:gray;
                border-radius:5px;
                cursor:pointer;
            }
        ''')
        self.close_btn.setStyleSheet('''
            QPushButton{
                background:#F76677;
                border-radius:5px;
                }
            QPushButton:hover{
                background:red;
                }''')
        self.status_label.setStyleSheet('''
            QLabel{
                background:#F7D674;
                border-radius:5px;
                }
        ''')

    # 初始化UI界面
    def init_ui(self):
        # 窗口布局
        self.main_widget = QtWidgets.QWidget()
        self.main_widget.setObjectName("main_widget")
        self.main_layout = QtWidgets.QGridLayout()
        self.main_widget.setLayout(self.main_layout)

        # 标题
        self.title_lable = QtWidgets.QLabel("听者,如过眼云烟……")

        # 关闭按钮
        self.close_btn = QtWidgets.QPushButton("")  # 关闭按钮
        self.close_btn.setFixedSize(15,15)

        # 音乐状态按钮
        self.status_label = QtWidgets.QLabel("")
        self.status_label.setFixedSize(15,15)

        # 播放按钮
        play_icon = qta.icon("fa.play-circle",)
        self.play_btn = QtWidgets.QPushButton(play_icon,"")
        self.play_btn.setIconSize(QtCore.QSize(80, 80))
        self.play_btn.setFixedSize(82,82)
        self.play_btn.setObjectName("play_btn")

        # 下一首按钮
        next_icon = qta.icon("fa.play-circle-o")
        self.next_btn = QtWidgets.QPushButton(next_icon,"")
        self.next_btn.setIconSize(QtCore.QSize(80,80))
        self.next_btn.setFixedSize(82,82)
        self.next_btn.setObjectName("next_btn")

        # 进度条
        self.process_bar = QtWidgets.QProgressBar()
        self.process_value = 0
        self.process_bar.setValue(self.process_value)
        self.process_bar.setFixedHeight(5)
        self.process_bar.setTextVisible(False)

        self.main_layout.addWidget(self.close_btn,0,0,1,1)
        self.main_layout.addWidget(self.title_lable,0,1,1,1)
        self.main_layout.addWidget(self.status_label,1,0,1,1)
        self.main_layout.addWidget(self.play_btn, 1, 1, 1, 1)
        self.main_layout.addWidget(self.next_btn, 1, 2, 1, 1)
        self.main_layout.addWidget(self.process_bar,2,0,1,3)

        self.setCentralWidget(self.main_widget)

在上面的代码中,我们通过Qt内置的按钮控件QPushButton、标签控件QLabel、进度条控件QProgressBar等把播放器的基础界面构建好了,然后通过setStyleSheet()方法设置各个控件的样式,最终得到下面的界面:
在这里插入图片描述
顶部的边框有点丑丑的,我们通过setWindowFlag()将其隐藏起来:

self.setWindowFlag(QtCore.Qt.FramelessWindowHint)  # 隐藏边框

这样,完整且好看的界面就完成了,如下图所示:
在这里插入图片描述

二、获取网络歌曲

既然是音乐播放器,当然要能够播放音乐。我们创建的这个音乐播放器不能添加本地的音乐,那就只能播放网络的音乐了。州的先生(https://zmister.com)在网上找了很久,终于找到了一个免费稳定的音乐接口。请求这个接口会随机返回一个音乐的播放地址。正好符合我们的播放器的设定,就它了:

def run(self):
    reps = requests.post("https://api.uomg.com/api/rand.music?format=json")
    # print(reps.json())
    file_url = reps.json()['data']['url']
    self.finished_signal.emit(file_url)

我们将其用Qt的线程模块QThread包装起来,作为一个异步的子线程调用:
在这里插入图片描述
有了UI界面和网络音乐,下面我们UI界面上的控件与音乐的播放通过信号槽(事件响应)连接起来。

三、创建和链接信号槽

因为我们隐藏的UI界面自带的边框,所以没有了关闭按钮。我们之前创建了左侧小红点作为播放器关闭的按钮,接着还需要一个响应函数来关闭播放器:

# 关闭程序
def close_btn_event(self):
    self.close()
self.close_btn.clicked.connect(self.close_btn_event)

这样,点击小红点,播放器就可以关闭退出了。下面来处理音乐的播放。

在这里,我们借助Qt提供的QtMultimedia子模块中的QMediaPlayer来实现MP3音乐的播放,QtMultimedia的详细使用可见Qt的官方文档:https://doc.qt.io/qtforpython/PySide2/QtMultimedia/index.html#module-PySide2.QtMultimedia:

在这里插入图片描述
这个方法,接受一个MP3音乐的网络地址参数,然后通过配置,对其进行播放。

我们之前创建了一个继承于QThread的网络歌曲获取类GetMusicThread,通过创建另一个方法对其进行调用,并将完成信号(finished_signal)连接到init_player()方法即可实现网络歌曲的获取和播放:
在这里插入图片描述
在这里,next_music()方法调用GetMusicThread随机获取一首歌曲,然后将歌曲的URL地址返回给init_player()方法,以实现播放。

next_music()方法是播放歌曲的主要方法,播放按钮、下一首按钮、一首歌曲播放完之后自动播放下一首歌曲都可以调用它。

播放音乐按钮需要控制和判断音乐的状态,可通过QMediaPlayer的mediaStatus()方法获取,并以此来进行判断:
在这里插入图片描述
为了能够在播放完一首歌曲后自动获取和播放下一首歌曲,我们需要创建一个计时器,每隔一秒获取当前播放器的状态,判断其是否已经播放完了音乐,如果播放完了,就调用next_music()方法:

self.timer = QtCore.QTimer()
self.timer.setInterval(1000)
self.timer.start()
self.timer.timeout.connect(self.check_music_status)
def check_music_status(self):
    player_status = self.player.mediaStatus()
    player_duration = self.player.duration()
    # print("音乐时间:",player_duration)
    # print("当前播放器状态",player_status)
    if player_status == 7:
        self.next_music()

再经过一些细节调整,我们就完成了这个“听后即焚”的网络音乐播放器:

在这里插入图片描述
完整的代码可以前往州的先生在Gitee上的仓库(https://gitee.com/zmister/yunyan_music)查看。

本文首发于州的先生博客https://zmister.com,链接为:《使用PyQt5/PySide2编写一个极简的音乐播放器》,更多原创编程实战应用文章,欢迎前往阅读。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/y747702801/article/details/104267423

智能推荐

html标签语义,我的HTML标签语义归纳_weixin_39728124的博客-程序员秘密

Info完成时间: 2016年4月更新时间:转载请保留时间信息,以免误导查阅者!!内容有错误、不完整请帮忙指出,我会更新的!为什么根据语义归纳使用HTML标签有一个最重要的原则,那就是:根据标签的语义而不是根据标签的默认样式。举个例子:这是文章的第一段。这是文章的第二段。正确的做法应该是一个自然段一个p标签。像上面仅仅只是因为br标签能换行(换行是一种样式表现),所以才使用br标签来分割自然段,这...

ArcGIS API for JavaScript4.x 类的引用_arcgis js api引入方法_GISer_CV攻城狮的博客-程序员秘密

ArcGIS API for JavaScript引用<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=e

ColorFilter 简介_color filter_放大的EZ的博客-程序员秘密

文章目录1、概述2、ColorMatrixColorFilter3、 LightingColorFilter4、PorterDuffColorFilter1、概述ColorFilter主要用来处理颜色,这里将讲解它的三个子类,ColorMatrixColorFilter,LightingColorFilter以及PorterDuffColorFilter。2、ColorMatrixColorFilter这个类主要是使用matrix也就是矩阵对颜色做运算,矩阵的形态如下:颜色值和该矩阵的换算关系

linux 浮动ip 出口,在Linux 双机下自己手动实现浮动ip技术_weixin_36068796的博客-程序员秘密

两台Linux服务器,一台为主机(IP:124.158.26.30)对外提供了一定的网络服务,另一台从机(IP:124.158.26.31)能提供相同的服务,但ip地址没有对外部公开客户端连接的都是124.158.26.30这个ip地址,如果主机故障,则会使网络服务暂时中断,时间越长造成损失越大由于没有采用双机热备技术,考虑自己用Linux脚本来实现简单的浮动ip技术,当主机故障时从机获取124....

matlab脚本批量处理数据-重命名-移动_Bankeey的博客-程序员秘密

需要批量处理数据,对文件夹下的文件进行重命名,然后再移动重命名后的文件

如何设计优秀的 API_代码兔的博客-程序员秘密

API的设计是编程中最困难的事情。甚至有人认为,哪怕你已经有着十年的相关经验,也仅仅只能接触尝试API的设计。我们也曾经或多或少的为了那些缺乏经验的程序员所设计的一些API吃了苦头。然而,如果你能在这个过程中获得了一位优秀的导师对你进行指点,那么你的进步会呈几何速度提升。本文作者就从他的导师那学会了一套不受框条约束的方法,称之为“90-9-0.9”,可能最难的还是剩下的那0.1。原文内容如

随便推点

unigui快速使用figma的css样式_figma右边css怎么展示_winfredzhang的博客-程序员秘密

figma是快速开发原型页面的在线编辑利器,而且免费输出css样式,想到可以使用它来生成css样式表,为unigui所用,试了一下基本实现。1、打开figma的模板。2、点选组件。3、复制css中代码。4、在unigui的ServerModule中复制,取名.someclass1的。5、在MainForm窗体上拖拽一个label组件6、设置clientEve...

【问题已解决】The server time zone value ‘?й???????‘ is unrecognized or represents more than one time zone_fishineye的博客-程序员秘密

The server time zone value ‘?й???’ is unrecognized or represents more than one time zone错误原因:本人用最新版本的mysql数据库使用原mysql5.1.38不会出现该问题,但会提示版本驱动过旧的情况使用了Mysql最新版驱动所以报错新版驱动名字为 driverClass=“com.mysql.cj.jdbc.Driver”解决方案:方案1、在项目代码-数据库连接URL后,加上 ?server

subline 写php,用subline text写PHP后台服务器POST请求_第一反应急救的博客-程序员秘密

1 运行XAMPP程序,看到Apache Web Server 是Running状态即可2 打开Subline text ,新建一个PHP文件,选择保存路径:应用程序->XAMPP->htdocs,点击Save 保存//$_POST 表示接口支持POST请求,通过POST方式获取参数3 在新建的PHP文件中写入代码,这里以简单的通过POST方式获取登录验证,用户名为dudu.密码123...

5 FFmpeg从入门到精通-FFmpeg流媒体_ffmpeg 监听_SuperMiguaL的博客-程序员秘密

5.FFmpeg流媒体 5.1 FFmpeg发布与录制RTMP流 5.1.1 RTMP参数说明 5.1.2 RTMP参数举例 1.rtmp_app参数 2.rtmp_playpath参数 3.rtmp_pageurl、tmp_swfurl、rtmp_tcurl参数 5.2 FFmpeg录制RTSP流 5.2.1 RTSP参数说明 5.2.2 RTSP参数使用举例 1.TCP方式录制RTSP直播流 2.User-Agent设置参数

JavaEE-面向对象_dannygu12138的博客-程序员秘密

JAVA-面向对象OO文章目录JAVA-面向对象OO面向对象 (Object-Oriented)面向对象编程思想面向对象:面向过程:面向对象和面向过程的区别:面向对象的好处:面向对象的特征:类和对象类和对象类的说明对象的创建和使用创建对象的内存理解成员变量和局部变量匿名对象的理解和使用封装 (Encapsulation)封装的概述private关键字Getter和Setter变量访问原则和this关键字构造方法概述构造方法的注意事项创建对象内存理解(三个初始化过程)静态(static)静态的概述静态变量的

java 8 lambda表达式list操作分组、过滤、求和、最值、排序、去重_lambda list sum_gsls200808的博客-程序员秘密

java8的lambda表达式提供了一些方便list操作的方法,主要涵盖分组、过滤、求和、最值、排序、去重。跟之前的传统写法对比,能少写不少代码。新建实体类package com.vvvtimes.vo;import java.math.BigDecimal;import java.util.Date;public class User { private Long ...