Python用Pyqt5制作音乐播放器

具体效果如下

需要实现的功能主要的几个有:

1、搜索结果更新至当前音乐的列表,这样播放下一首是搜素结果的下一首

2、自动播放

3、滚动音乐文本

4、音乐进度条

5、根据实际情况生成音乐列表。我这里的是下面的情况,音乐文件的格式是 

歌名_歌手.mp3

所以根据需求修改 find_mp3_files 方法,我这里返回的是

[ {"path":音乐文件路径,

"music":歌名,

"singer":歌手},

{"path":音乐文件路径,

"music":歌名,

"singer":歌手},

...]

 全部代码在此,试试吧

import fnmatch
import os
import random
import sys

from PyQt5.QtGui import QPalette, QBrush, QPixmap
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QSlider, QLabel, \
    QTableWidget, QLineEdit, QTableWidgetItem
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
from PyQt5.QtCore import QUrl, Qt, QTimer


class MusicPlayer(QMainWindow):
    def __init__(self):
        super().__init__()
        self.music_path = "F://wyy"  # 音乐文件夹,可以有子文件夹
        self.start_x = 10
        self.x_step = 100
        self.start_y = 10
        self.y_step = 40
        self.window_w, self.window_h = 500, 800
        self.music_list = self.find_mp3_files()
        self.show_list = self.music_list

        self.duration = 1
        self.position = 0
        self.text = "歌曲未加载"

        self.current_index = -1
        self.current_music = self.show_list[self.current_index]['music']
        self.current_singer = self.show_list[self.current_index]['singer']
        self.current_path = self.show_list[self.current_index]['path']

        self.status = True
        self.update_label = True
        self.init_ui()
        print("配置加载完成")

    def init_ui(self):
        self.setWindowTitle("音乐播放器")
        self.resize(self.window_w, self.window_h)
        self.setMinimumSize(self.window_w, self.window_h)
        self.setMaximumSize(self.window_w, self.window_h)
        palette = QPalette()  # 主界面背景
        palette.setBrush(QPalette.Background, QBrush(QPixmap("imgs/21.jpg")))
        self.setPalette(palette)

        self.player = QMediaPlayer()

        self.table_widget = QTableWidget(0, 2, parent=self)  # 检测结果列表
        self.table_widget.setHorizontalHeaderLabels(['歌手', '歌曲'])  # 设置列表头
        self.table_widget.verticalHeader().hide()  # 隐藏行索引
        self.table_widget.move(10, 150)
        self.table_widget.resize(500, 600)
        self.table_widget.cellClicked.connect(self.line_clicked)
        self.table_widget.setColumnWidth(0, 200)
        self.table_widget.setColumnWidth(1, 270)
        self.table_widget.setEditTriggers(QTableWidget.NoEditTriggers)
        self.table_widget.setStyleSheet("QTableWidget {background-image: url('imgs/11.jpg');}")
        self.load_music()

        self.play_button = QPushButton("播放", self)
        self.play_button.clicked.connect(self.play_current_music)
        self.play_button.move(self.start_x, self.start_y)
        self.change_button = QPushButton("暂停", self)
        self.change_button.clicked.connect(self.change_music_status)
        self.change_button.move(self.start_x + self.x_step, self.start_y)
        self.play_pre_button = QPushButton("上一首", self)
        self.play_pre_button.clicked.connect(self.play_pre)
        self.play_pre_button.move(self.start_x, self.start_y + self.y_step)
        self.play_next_button = QPushButton("下一首", self)
        self.play_next_button.clicked.connect(self.play_next)
        self.play_next_button.move(self.start_x + self.x_step, self.start_y + self.y_step)

        self.search_text = QLineEdit(self)
        self.search_text.resize(200, 30)
        self.search_text.move(self.start_x + 3 * self.x_step + 10, self.start_y)
        self.search_btn = QPushButton("搜索", self)
        self.search_btn.clicked.connect(self.search_music)
        self.search_btn.move(self.start_x + 2 * self.x_step + 10, self.start_y)

        self.music_label = QLabel(self.text, self)
        self.music_label.resize(self.window_w - self.start_x, 30)
        self.music_label.move(self.start_x, self.start_y + 2 * self.y_step)
        self.music_label.setAlignment(Qt.AlignCenter)

        self.volume_slider = QSlider(Qt.Horizontal, self)
        self.volume_slider.setRange(0, 100)
        self.volume_slider.setValue(50)
        self.volume_slider.setTickPosition(QSlider.TicksBelow)
        self.volume_slider.setTickInterval(10)
        self.volume_slider.resize(200, 30)
        self.volume_slider.valueChanged.connect(self.change_volume)
        self.volume_slider.move(self.start_x + 2 * self.x_step + 50, self.start_y + self.y_step + 10)

        self.music_pro = QLabel(self)
        self.music_pro_width = self.window_w - self.start_x
        self.music_pro.resize(self.music_pro_width, 10)
        self.music_pro.move(self.start_x, self.start_y + 2 * self.y_step + 40)
        self.music_pro.setStyleSheet("background:'#123456'")

        self.timer = QTimer()
        self.timer.timeout.connect(self.scroll_text)
        self.timer.start(500)

        self.player.stateChanged.connect(self.handle_player_status_changed)
        self.player.mediaStatusChanged.connect(self.handle_media_status_changed)
        self.player.durationChanged.connect(self.update_duration)
        self.player.positionChanged.connect(self.update_position)

    def change_music_status(self):
        if self.status:
            self.player.pause()
            self.status = False
            self.change_button.setText('继续')
            print("已暂停当前音乐", self.current_music)
        else:
            self.status = True
            self.player.play()
            self.change_button.setText('暂停')
            print("已继续当前音乐", self.current_music)

    def handle_media_status_changed(self, status):
        if status == QMediaPlayer.EndOfMedia:
            self.play_next()

    def handle_player_status_changed(self, state):
        if state == QMediaPlayer.PlayingState:
            self.update_label = True
        elif state == QMediaPlayer.StoppedState:
            self.update_label = False

    def search_music(self):
        text = self.search_text.text()
        if text:
            self.show_list = []
            for i in self.music_list:
                for j in i.values():
                    if text in j:
                        self.show_list.append(i)
                        break
            self.load_music()
            print("查询结束")
        else:
            self.music_list = self.find_mp3_files()  # 从本地重新加载
            self.show_list = self.music_list 
            self.load_music()
            print('>>>>>>>>>>>>>>>未查询到相关音乐,已重新加载列表')

    def clear_table(self):
        self.table_widget.clearContents()
        self.table_widget.setHorizontalHeaderLabels(['歌手', '歌曲'])  # 设置列表头
        self.table_widget.setRowCount(0)
        print("已更新列表")

    def line_clicked(self, row, column):
        self.current_index = row
        self.update_current_music()
        print("点击了", self.current_music, self.current_singer)

    def load_music(self):
        self.clear_table()
        n = 0
        for i in self.show_list:
            self.table_widget.setRowCount(n + 1)
            self.table_widget.setItem(n, 0, QTableWidgetItem(i['singer']))
            self.table_widget.setItem(n, 1, QTableWidgetItem(i['music']))
            n += 1
        print('已重新加载音乐列表')

    def play_current_music(self):
        if self.current_index == -1:
            self.current_index = 0
            self.update_current_music()
        print(self.current_index)
        self.play_music()

    def play_music(self):
        self.player.setMedia(QMediaContent(QUrl.fromLocalFile(self.current_path)))
        self.player.play()
        self.text = f"当前播放: {self.current_music} —— {self.current_singer} "
        self.music_label.setText(self.text)
        print("正在播放:", self.current_music)

    def update_current_music(self):
        self.current_path = self.show_list[self.current_index]['path']
        self.current_singer = self.show_list[self.current_index]['singer']
        self.current_music = self.show_list[self.current_index]['music']
        print("已更新当前音乐")

    def play_pre(self):
        print("播放上一首")
        for i, j in enumerate(self.show_list):
            if self.current_path == j['path']:
                if i != 0:
                    self.current_index = i - 1
                else:
                    self.current_index = -1
                break
        self.update_current_music()
        print("切换音乐为", self.current_music)
        self.play_music()

    def play_next(self):
        print("播放下一首")
        for i, j in enumerate(self.show_list):
            if self.current_path == j['path']:
                if i != len(self.show_list) - 1:
                    self.current_index = i + 1
                else:
                    self.current_index = 0
                break
        self.update_current_music()
        print("切换音乐为", self.current_music)
        self.play_music()

    def change_volume(self, value):
        self.player.setVolume(value)
        print("设置音量为", value)

    def set_position(self):
        self.music_pro.resize(int(self.position / self.duration * self.music_pro_width), 10)
        c = int(self.position / self.duration * 255)
        h = self.rgb2hex(c, c, c)
        self.music_pro.setStyleSheet(f"background:'{h}'")

    def update_duration(self, duration):
        if not self.update_label:
            return
        self.duration = duration

    def update_position(self, position):
        if not self.update_label:
            return
        self.position = position
        self.set_position()

    def scroll_text(self):
        current_text = self.music_label.text()
        scroll_text = current_text[1:] + current_text[0]
        self.music_label.setText(scroll_text)
        self.music_label.setStyleSheet(f"color:{self.rgb2hex(*self.random_color())}")

    def rgb2hex(self, r, g, b):
        return "#{:02x}{:02x}{:02x}".format(r, g, b)

    def find_mp3_files(self):  # 生成音乐文件列表,根据需求自定义
        mp3_files = []
        for root, dirs, files in os.walk(self.music_path):
            for file in files:
                if fnmatch.fnmatch(file, '*.mp3'):
                    if '_' in file:
                        r = {'music': file.split('_')[0],
                             'singer': file.split('_')[1].split('.')[0],
                             'path': os.path.join(root, file)}
                        mp3_files.append(r)
        return mp3_files

    def random_color(self):  # 随机颜色
        r, g, b = random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)
        return r, g, b


if __name__ == "__main__":
    app = QApplication(sys.argv)
    player = MusicPlayer()
    player.show()
    sys.exit(app.exec_())

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/802783.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Calibration相机内参数标定

1.环境依赖 本算法采用张正友相机标定法进行实现,内部对其进行了封装。 环境依赖为 ubuntu20.04 opencv4.2.0 yaml-cpp yaml-cpp安装方式: (1)git clone https://github.com/jbeder/yaml-cpp.git #将yaml-cpp下载至本地 &a…

Fastjson解析JSON时key对应的value存在多个英文双引号解决

情景 如上图所示,经常在解析json时会出现因双引号报错的问题。 fastjson解决方案 JSONObject jsonfile JSONObject.parseObject(json, Feature.OrderedField);JSONArray jsonArray jsonfile.getJSONObject("result").getJSONArray("items");…

Linux网络编程-socket套接字使用详解

1.概念 在Linux中,套接字(socket)是一种通信机制,用于实现不同进程之间或同一主机上的不同线程之间的数据交换。它是网络编程的基础,允许应用程序通过网络进行通信,也可以在同一台机器上的不同进程间进行通…

ajax实时监控input搜索框并给提示词的事实举例的超全版本(上-不用字典树)

前言 感觉前面直接放概念和字典树还是差了点,有的看了概念还是没有思路的,于是写这篇文章来举例子,首先这不不包含字典树的版本,用字典树的版本等下会发。 需要的技术 jsp和ajax简单的理解,做示例的后端框架是sprin…

物流智能锁在物流锁控中的应用设计方案

一、案例介绍与问题剖析 (一)案例概述 某知名物流企业,拥有广泛的运输网络和多样化的客户群体,涵盖了制造业、零售业等多个领域。然而,随着业务规模的不断扩大,其在货物锁控方面遇到了一系列棘手的问题。…

Java | Leetcode Java题解之第238题除自身以外数组的乘积

题目: 题解: class Solution {public int[] productExceptSelf(int[] nums) {int length nums.length;// L 和 R 分别表示左右两侧的乘积列表int[] L new int[length];int[] R new int[length];int[] answer new int[length];// L[i] 为索引 i 左侧…

[C++] 深度剖析C_C++内存管理机制

文章目录 内存分布内存分布图解 C语言中动态内存管理方式malloc:callocrealloc C内存管理方式内置类型**自定义类型** operator new & operator deleteoperator new & operator delete函数operator newoperator delete **new T[N]** 与**delete[]** **定位new表达式(pl…

JavaScript基础(十四)

函数 很多人一看到这两个字就头大,可能由于多年被数学摧残有不小阴影,放心,我们这里的函数不是那些东西,在编程中我们的函数指的是: 程序的基本单元,是完成特定任务的代码语句块。 我们在写程序时,可能会…

【保姆级】Python项目部署到Linux生产环境(uwsgi+python+flask+nginx服务器)

1.安装python 我这里是3.9.5版本 安装依赖: yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make -y 根据自己的需要下载对应的python版本: cd /usr/local wget https://www.python.or…

springboot机场投诉管理平台-计算机毕业设计源码22030

摘要 随着航空运输业的迅速发展,机场的客流量不断增加,旅客对机场服务的质量和效率也提出了更高的要求。为了提高机场的服务质量,及时处理旅客的投诉,建立一个高效、便捷的机场投诉管理平台显得尤为重要。 本项目旨在设计与实现一…

# ffmpeg 工具使用

文章目录 ffmpeg 工具使用1.图片转换2.图片转视频3.截取片段4. 视频格式转换5. 视频转图片方法一:方法二:生成更清晰无压缩的图片方式: ffmpeg 工具使用 windows安装教程:https://blog.csdn.net/csdn_yudong/article/details/129…

Python一对一辅导答疑|Rust 德国

你好,我是悦创。 下面是答疑内容。 在 Rust 中,方法的调用方式通常取决于它们是如何定义的。在你的例子中,print_drink方法最初是作为一个接受Drink类型实例作为参数的关联函数(类似于静态方法)定义的。后来&#xff…

紫外测熔融实验结果温度和abs作折线图和求一阶导最大值

import numpy as np import pandas as pd from pyecharts.charts import Line from pyecharts import options as opts from matplotlib import pyplot as plt import xlrd # 读取 csv 文件 data pd.read_excel(F:/LJX/lc8.xls)# 假设 csv 文件中有两列数据:x 和 y…

[transformer] Attention is all you need

1、目的 提出一种新的网络结构,不用CNN或者RNN,只基于self-attention 2、方法 * Norm: Layer Normalization 1)Encoder -> -> self-attention的k、v、q来自上一个encoder层 2)Decoder -> 由于每个位置i的预测只能参考i…

跨境电商与TikTok达人带货:未来合作模式与市场机遇

随着全球社交媒体技术的不断进步和消费者行为的持续变化,跨境电商与TikTok达人合作的模式正展现出前所未有的多元化和专业化趋势。这种合作不仅推动了品牌的国际化进程,也为消费者带来了更加丰富和个性化的购物体验。本文Nox聚星将和大家探讨未来跨境电商…

php反序列化--1--PHP序列化

目录 一、什么是php序列化? 二、在php中怎么进行序列化? 三、不同数据类型的序列化后的表达方式 1、空-NULL 2、整形 3、浮点型 4、boolean型 5、字符型 6、数组 7、对象序列化-公有修饰符 8、对象序列化-私有修饰符 9、对象序列化-保护修饰…

C++ 回溯算法

什么时候不需要startIndex? 全排列:1在[1,2]中已经使用过了,但是在[2,1]中还要在使用一次1,所以处理排列问题就不用使用startIndex了;电话号码的字母组合:如果是多个集合取组合,各个集合之间相互不影响&a…

景区导航导览系统:基于AR技术+VR技术的功能效益全面解析

在数字化时代背景下,游客对旅游体验的期望不断提升。游客们更倾向于使用手机作为旅行的贴身助手,不仅因为它能提供实时、精准的导航服务,更在于其融合AR(增强现实)、VR(虚拟现实)等前沿技术&…

汽车免拆诊断案例 | 卡罗拉急加速抖动故障排除

车型信息 2017年改款卡罗拉,排量1.2T,行驶里程48800公里。 故障现象 车辆不管在什么状态下,只要是平缓加速,都不会有抖动。车辆静止时,急加速时,也不会有抖动。但是车速达40公里/小时以上,急加…

SQL注入问题

一、什么是sql注入 public class TestSql {public static void main(String[] args) {Scanner inScanner new Scanner(System.in);System.out.println("请输入用户名");String username inScanner.nextLine();System.out.println("请输入密码");String …