pygame编写音乐播放器的实现代码示例


Posted in Python onNovember 19, 2019

1、准备工作

ide:pycharm
python:3.7
三方包:pygame、pyinstaller、mutagen
几首mp3格式的歌

2、开始

2.1 设计说明

1、包含 上一首、下一首、暂停/播放、快进/快退、显示当前播放的歌曲名称、显示播放进度条
2、使用pygame.mixer
3、随机播放磁盘某个目录及其子目录下的mp3文件
4、上一首、下一首用随机选择choice(list) 实现
5、进度条用按照一定速度移动进度图片来实现,过程中处理暂停、快进
6、歌曲快进播放用pygame.mixer.music.play(0,d_song_time) 实现
7、暂停用pygame.mixer.music.pause() 实现
8、播放用pygame.mixer.music.unpause() 实现
9、用mutagen.mp3来获取mp3信息

2.2 代码逻辑

收集某个目录下的所有mp3

# 收集某个目录及子目录下的MP3格式的文件
# 返回歌曲路径、歌曲时长
# [['E:\\musics\\Mirror_Yohee_128K.mp3', 236], ['E:\\musics\\over here_Nobigdyl_128K.mp3', 188], ['E:\\musics\\尘_薛之谦_128K.mp3', 282], ['E:\\musics\\aaa\\尘_薛之谦_128K.mp3', 282]]
def collect_songs(fidir):
  musics =[]
  for root, dirs, files in os.walk(fidir):
    for file in files:
      tmp =[]
      if file.endswith('mp3'):
        file = os.path.join(root,file)
        song = MP3(file)
        duration = round(song.info.length)
        tmp.append(file)
        tmp.append(duration)
        musics.append(tmp)
  return musics

显示歌曲名称

# 把歌曲名字显示在播放器上
def draw_song_name(music):
  # 取歌曲名
  music_name = music[0].split("\\")[-1]
  # print(music_name)
  wbk_obj = font_obj.render(music_name, True, (0, 255, 255))
  k_obj = wbk_obj.get_rect()
  k_obj.center = (340, 200)
  screen.blit(wbk_obj, k_obj)
  pygame.display.update()

播放歌曲

# 随机播放一首歌
def sing_a_song(musics):
  # 随机选择一首音乐
  music = choice(musics)
  print(type(musics))
  pygame.mixer.music.load(music[0])
  pygame.mixer.music.play()
  print('开始播放:%s -- %s秒'%(music[0] , str(music[1])))
  return music

显示播放进度

# 播放进度显示
def move(current_time,start_time,pause_duration_time,c_music):
  if pause_end_time == 0 and pause_start_time != 0:
    duration_time = round(pause_start_time - start_time - pause_duration_time)
  else:
    duration_time = round(current_time - start_time - pause_duration_time)
  song_total_time = c_music[1]
  speed = (end_x-begin_x)/song_total_time
  current_x = begin_x + duration_time*speed
  try:
    screen.blit(dian,(current_x,148))
    pygame.display.update()
  except:
    print(current_time)
    print(start_time)
    print(pause_duration_time)
    exit()

快进快退功能

# 快进快退功能
def kuaijin(jindu_x,c_music):
  # 要跳转到的距离d_x
  d_x = jindu_x - begin_x
  song_total_time = c_music[1]
  # 要跳转到的时间d_song_time
  d_song_time = round(song_total_time*(d_x/560),1)
  # 将歌曲快进到d_song_time
  pygame.mixer.music.play(0,d_song_time)

画播放控件

# 画播放控件
def draw_kongjian(is_sing,is_pause):
  # 画进度条
  # 画一条宽度为2的线,y高度为149,x从40到600,颜色为(0,100,100)
  pygame.draw.line(screen, (0, 100, 100), (40, 149), (600, 149), 2)
  # 画播放、暂停按钮
  # 先画圆边框,半径20
  pygame.draw.circle(screen, (0, 255, 255), (x + 80, 100), 20, 2)
  # 画三角形,开始播放
  pygame.draw.line(screen, (0, 255, 255), (x + 73.7, 107.5), (x + 73.7, 93), 2) # 竖线
  # 如果正在播放且没有暂停
  if is_sing and not is_pause:
    # 隐藏三角形
    pygame.draw.line(screen, (0, 89, 115), (x + 73.7, 107.5), (x + 87.3, 100), 2)
    pygame.draw.line(screen, (0, 89, 115), (x + 73.7, 93), (x + 87.3, 100), 2)
    # 显示第二条竖线
    pygame.draw.line(screen,(0,255,255),(x+83.7,107.5),(x+83.7,93),2)
  else:
    # 隐藏第二条竖线
    pygame.draw.line(screen, (0, 89, 115), (x + 83.7, 107.5), (x + 83.7, 93), 2)
    # 显示三角形
    pygame.draw.line(screen,(0,255,255),(x+73.7,107.5),(x+87.3,100),2)
    pygame.draw.line(screen,(0,255,255),(x+73.7,93),(x+87.3,100),2)

  # 画上一首按钮
  pygame.draw.line(screen, (0, 255, 255), (x - 10, 110), (x - 10, 90), 2)
  pygame.draw.line(screen, (0, 255, 255), (x - 10, 100), (x + 10, 115), 2)
  pygame.draw.line(screen, (0, 255, 255), (x - 10, 100), (x + 10, 85), 2)
  pygame.draw.line(screen, (0, 255, 255), (x + 10, 115), (x + 10, 85), 2)

  # 画下一首按钮
  pygame.draw.line(screen, (0, 255, 255), (x + 170, 110), (x + 170, 90), 2)
  pygame.draw.line(screen, (0, 255, 255), (x + 170, 100), (x + 150, 115), 2)
  pygame.draw.line(screen, (0, 255, 255), (x + 170, 100), (x + 150, 85), 2)
  pygame.draw.line(screen, (0, 255, 255), (x + 150, 115), (x + 150, 85), 2)

主逻辑

1、画界面
2、如果没有在播放音乐,播放之
3、如果正在播放音乐,刷新播放进度
4、点击了上一首的处理
5、点击了暂停/播放的处理
6、点击了下一首的处理
7、快进/快退的处理

while True:
  # 第一步画背景
  screen.fill((0, 0, 0)) # ----------------新添加
  # 第二步添加背景图片
  bg = pygame.image.load(music_bg)
  screen.blit(bg, (0, 0))
  # 第四步,画控件
  draw_kongjian(is_sing,is_pause)

  # print("status:-------" + str(pygame.mixer.music.get_busy()))
  # 如果正在播放音乐,有bug == 当暂停后返回依旧是1
  if pygame.mixer.music.get_busy() == 1:
    is_sing = True
  else:
    is_sing = False

  # 如果没有在播放音乐
  if not is_sing:
    # 第五步,开始唱歌
    c_music = sing_a_song(musics)
    # 记录开始播放时间
    start_time = time.time()
    # 暂停时长置为0
    pause_start_time = pause_end_time = pause_duration_time = 0
    # 进度条开始位置重置为40
    begin_x = 40
    # 第六步,显示歌名
    draw_song_name(c_music)
    # 更改播放状态
    is_sing = not is_sing
  # 如果正在唱歌
  else:
    # 第六步,显示歌名
    draw_song_name(c_music)
    current_time = time.time()
    move(current_time, start_time, pause_duration_time, c_music)


  for event in pygame.event.get():
    if event.type == QUIT:
      pygame.quit()
      exit()
    if event.type == MOUSEBUTTONDOWN:
      # 如果点击了鼠标左键,取到当前鼠标的坐标
      pressed_array = pygame.mouse.get_pressed()
      if pressed_array[0] == 1:
        mouse_x, mouse_y = event.pos
        print('点击了左键,位置为(%d,%d)'%(mouse_x,mouse_y))
        # 判断点击了哪个按钮
        if 80 < mouse_y < 120:
          if x - 5 < mouse_x < x + 15:
            # 点击了上一首
            c_music = sing_a_song(musics)
            is_pause = False
            is_kuaijin = False
            # 记录开始时间
            start_time = time.time()
            # 暂停时长置为0
            pause_start_time = pause_end_time = pause_duration_time = 0
            # 进度条开始位置置为40
            begin_x = 40
            # 第六步,显示歌名
            draw_song_name(c_music)
            print('点击了上一首')
          elif x+60 < mouse_x < x+100:
            # 修改是否暂停的状态
            is_pause = not is_pause
            # 如果没有暂停
            if not is_pause:
              # 开始播放
              pygame.mixer.music.unpause()
              # 记录结束暂定时间
              pause_end_time = time.time()
              # 计算暂停时长
              pause_duration_time = pause_duration_time + pause_end_time - pause_start_time
              # 暂停结束,暂停结束开始时间均置为0
              pause_end_time = pause_start_time = 0
            # 如果暂停了
            else:
              # 暂停播放
              pygame.mixer.music.pause()
              # 记录开始暂定时间
              pause_start_time = time.time()

            print('点击了暂停')
          elif x+145 < mouse_x < x+170:
            # 点击了下一首
            c_music = sing_a_song(musics)
            is_pause = False
            is_kuaijin = False
            # 记录开始时间
            start_time = time.time()
            # 暂停时长置为0
            pause_start_time = pause_end_time = pause_duration_time =0
            # 进度条开始位置置为40
            begin_x = 40
            # 第六步,显示歌名
            draw_song_name(c_music)
            print('点击了下一首')
        # 如果点了进度条的某个位置
        elif 155> mouse_y >145:
          kuaijin(mouse_x,c_music)
          begin_x = mouse_x
          pause_end_time = pause_start_time = pause_duration_time = 0
          move(current_time,start_time,pause_duration_time,c_music)
          is_kuaijin = True
          print("快进")

    pygame.display.update()

 3、效果图

pygame编写音乐播放器的实现代码示例

刺猬牛逼!!!

4、完整代码

#-*- coding: utf-8 -*-
import os,time,sys
from sys import exit
import pygame
from pygame.locals import *
from mutagen.mp3 import MP3
from random import choice


def rp(relative_path):
  """ Get absolute path to resource, works for dev and for PyInstaller """
  try:
    # PyInstaller creates a temp folder and stores path in _MEIPASS
    base_path = sys._MEIPASS
  except Exception:
    base_path = os.path.abspath(".")

  return os.path.join(base_path, relative_path)

pygame.init()
screen = pygame.display.set_mode((640, 480), 0, 32)
pygame.display.set_caption("music")
# 初始化音乐播放器
pygame.mixer.init()
# 背景图片
music_bg = rp(os.path.join('src','music_bg.jpg'))
# 进度点图片
dian_filename = rp(os.path.join('src','dian.jpg'))
dian = pygame.image.load(dian_filename)
# 字体
font_obj = pygame.font.Font('C:\Windows\Fonts\simsun.ttc',20)
# 偏移量基础值
x = 80
# 进度条开始x坐标
begin_x = 40
# 进度条结束x坐标
end_x = 600
# 是否正在播放歌曲,默认未播放
is_sing = False
# 是否暂停,默认未暂停
is_pause = False
# 是否快进了
is_kuaijin = False
# 快进后x坐标
jindu_x = -1
# 定义当前歌曲变量
global c_music
# 定义歌曲开始播放时间、当前时间、开始暂停时间、结束暂停时间
global start_time, current_time, pause_start_time, pause_end_time,pause_duration_time
pause_start_time =0
pause_end_time =0
pause_duration_time =0




# 把歌曲名字显示在播放器上
def draw_song_name(music):
  # 取歌曲名
  music_name = music[0].split("\\")[-1]
  # print(music_name)
  wbk_obj = font_obj.render(music_name, True, (0, 255, 255))
  k_obj = wbk_obj.get_rect()
  k_obj.center = (340, 200)
  screen.blit(wbk_obj, k_obj)
  pygame.display.update()


# 收集某个目录及子目录下的MP3格式的文件
# 返回歌曲路径、歌曲时长
# [['E:\\musics\\Mirror_Yohee_128K.mp3', 236], ['E:\\musics\\over here_Nobigdyl_128K.mp3', 188], ['E:\\musics\\尘_薛之谦_128K.mp3', 282], ['E:\\musics\\aaa\\尘_薛之谦_128K.mp3', 282]]
def collect_songs(fidir):
  musics =[]
  for root, dirs, files in os.walk(fidir):
    for file in files:
      tmp =[]
      if file.endswith('mp3'):
        file = os.path.join(root,file)
        song = MP3(file)
        duration = round(song.info.length)
        tmp.append(file)
        tmp.append(duration)
        musics.append(tmp)
  return musics

musics = collect_songs('E:\\musics')
print(musics)

# 随机播放一首歌
def sing_a_song(musics):
  # 随机选择一首音乐
  music = choice(musics)
  print(type(musics))
  pygame.mixer.music.load(music[0])
  pygame.mixer.music.play()
  print('开始播放:%s -- %s秒'%(music[0] , str(music[1])))
  return music


# 画代表当前进度的圆点
# 画一个直径为5个圆点,放在100,150的位置,颜色为(0,255,255)
# dian = pygame.draw.circle(screen,(0,255,255),(begin_x,150),6)


# 画播放控件
def draw_kongjian(is_sing,is_pause):
  # 画进度条
  # 画一条宽度为2的线,y高度为149,x从40到600,颜色为(0,100,100)
  pygame.draw.line(screen, (0, 100, 100), (40, 149), (600, 149), 2)
  # 画播放、暂停按钮
  # 先画圆边框,半径20
  pygame.draw.circle(screen, (0, 255, 255), (x + 80, 100), 20, 2)
  # 画三角形,开始播放
  pygame.draw.line(screen, (0, 255, 255), (x + 73.7, 107.5), (x + 73.7, 93), 2) # 竖线
  # 如果正在播放且没有暂停
  if is_sing and not is_pause:
    # 隐藏三角形
    pygame.draw.line(screen, (0, 89, 115), (x + 73.7, 107.5), (x + 87.3, 100), 2)
    pygame.draw.line(screen, (0, 89, 115), (x + 73.7, 93), (x + 87.3, 100), 2)
    # 显示第二条竖线
    pygame.draw.line(screen,(0,255,255),(x+83.7,107.5),(x+83.7,93),2)
  else:
    # 隐藏第二条竖线
    pygame.draw.line(screen, (0, 89, 115), (x + 83.7, 107.5), (x + 83.7, 93), 2)
    # 显示三角形
    pygame.draw.line(screen,(0,255,255),(x+73.7,107.5),(x+87.3,100),2)
    pygame.draw.line(screen,(0,255,255),(x+73.7,93),(x+87.3,100),2)

  # 画上一首按钮
  pygame.draw.line(screen, (0, 255, 255), (x - 10, 110), (x - 10, 90), 2)
  pygame.draw.line(screen, (0, 255, 255), (x - 10, 100), (x + 10, 115), 2)
  pygame.draw.line(screen, (0, 255, 255), (x - 10, 100), (x + 10, 85), 2)
  pygame.draw.line(screen, (0, 255, 255), (x + 10, 115), (x + 10, 85), 2)

  # 画下一首按钮
  pygame.draw.line(screen, (0, 255, 255), (x + 170, 110), (x + 170, 90), 2)
  pygame.draw.line(screen, (0, 255, 255), (x + 170, 100), (x + 150, 115), 2)
  pygame.draw.line(screen, (0, 255, 255), (x + 170, 100), (x + 150, 85), 2)
  pygame.draw.line(screen, (0, 255, 255), (x + 150, 115), (x + 150, 85), 2)

# 播放进度显示
def move(current_time,start_time,pause_duration_time,c_music):
  if pause_end_time == 0 and pause_start_time != 0:
    duration_time = round(pause_start_time - start_time - pause_duration_time)
  else:
    duration_time = round(current_time - start_time - pause_duration_time)
  song_total_time = c_music[1]
  speed = (end_x-begin_x)/song_total_time
  current_x = begin_x + duration_time*speed
  try:
    screen.blit(dian,(current_x,148))
    pygame.display.update()
  except:
    print(current_time)
    print(start_time)
    print(pause_duration_time)
    exit()

# 快进快退功能
def kuaijin(jindu_x,c_music):
  # 要跳转到的距离d_x
  d_x = jindu_x - begin_x
  song_total_time = c_music[1]
  # 要跳转到的时间d_song_time
  d_song_time = round(song_total_time*(d_x/560),1)
  # 将歌曲快进到d_song_time
  pygame.mixer.music.play(0,d_song_time)




while True:
  # 第一步画背景
  screen.fill((0, 0, 0)) # ----------------新添加
  # 第二步添加背景图片
  bg = pygame.image.load(music_bg)
  screen.blit(bg, (0, 0))
  # 第四步,画控件
  draw_kongjian(is_sing,is_pause)

  # print("status:-------" + str(pygame.mixer.music.get_busy()))
  # 如果正在播放音乐,有bug == 当暂停后返回依旧是1
  if pygame.mixer.music.get_busy() == 1:
    is_sing = True
  else:
    is_sing = False

  # 如果没有在播放音乐
  if not is_sing:
    # 第五步,开始唱歌
    c_music = sing_a_song(musics)
    # 记录开始播放时间
    start_time = time.time()
    # 暂停时长置为0
    pause_start_time = pause_end_time = pause_duration_time = 0
    # 进度条开始位置重置为40
    begin_x = 40
    # 第六步,显示歌名
    draw_song_name(c_music)
    # 更改播放状态
    is_sing = not is_sing
  # 如果正在唱歌
  else:
    # 第六步,显示歌名
    draw_song_name(c_music)
    current_time = time.time()
    move(current_time, start_time, pause_duration_time, c_music)


  for event in pygame.event.get():
    if event.type == QUIT:
      pygame.quit()
      exit()
    if event.type == MOUSEBUTTONDOWN:
      # 如果点击了鼠标左键,取到当前鼠标的坐标
      pressed_array = pygame.mouse.get_pressed()
      if pressed_array[0] == 1:
        mouse_x, mouse_y = event.pos
        print('点击了左键,位置为(%d,%d)'%(mouse_x,mouse_y))
        # 判断点击了哪个按钮
        if 80 < mouse_y < 120:
          if x - 5 < mouse_x < x + 15:
            # 点击了上一首
            c_music = sing_a_song(musics)
            is_pause = False
            is_kuaijin = False
            # 记录开始时间
            start_time = time.time()
            # 暂停时长置为0
            pause_start_time = pause_end_time = pause_duration_time = 0
            # 进度条开始位置置为40
            begin_x = 40
            # 第六步,显示歌名
            draw_song_name(c_music)
            print('点击了上一首')
          elif x+60 < mouse_x < x+100:
            # 修改是否暂停的状态
            is_pause = not is_pause
            # 如果没有暂停
            if not is_pause:
              # 开始播放
              pygame.mixer.music.unpause()
              # 记录结束暂定时间
              pause_end_time = time.time()
              # 计算暂停时长
              pause_duration_time = pause_duration_time + pause_end_time - pause_start_time
              # 暂停结束,暂停结束开始时间均置为0
              pause_end_time = pause_start_time = 0
            # 如果暂停了
            else:
              # 暂停播放
              pygame.mixer.music.pause()
              # 记录开始暂定时间
              pause_start_time = time.time()

            print('点击了暂停')
          elif x+145 < mouse_x < x+170:
            # 点击了下一首
            c_music = sing_a_song(musics)
            is_pause = False
            is_kuaijin = False
            # 记录开始时间
            start_time = time.time()
            # 暂停时长置为0
            pause_start_time = pause_end_time = pause_duration_time =0
            # 进度条开始位置置为40
            begin_x = 40
            # 第六步,显示歌名
            draw_song_name(c_music)
            print('点击了下一首')
        # 如果点了进度条的某个位置
        elif 155> mouse_y >145:
          kuaijin(mouse_x,c_music)
          begin_x = mouse_x
          pause_end_time = pause_start_time = pause_duration_time = 0
          move(current_time,start_time,pause_duration_time,c_music)
          is_kuaijin = True
          print("快进")

    pygame.display.update()

5、打包为exe

请查看另一篇文章

pyinstaller打包exe踩过的坑

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python3 实现的人人影视网站自动签到
Jun 19 Python
Python表示矩阵的方法分析
May 26 Python
新手如何快速入门Python(菜鸟必看篇)
Jun 10 Python
Pycharm编辑器技巧之自动导入模块详解
Jul 18 Python
Python编程使用NLTK进行自然语言处理详解
Nov 16 Python
python Flask 装饰器顺序问题解决
Aug 08 Python
Python socket实现的简单通信功能示例
Aug 21 Python
python文件拆分与重组实例
Dec 10 Python
numpy.linalg.eig() 计算矩阵特征向量方式
Nov 29 Python
python打开音乐文件的实例方法
Jul 21 Python
python 三种方法实现对Excel表格的读写
Nov 19 Python
关于python中remove的一些坑小结
Jan 04 Python
pyinstaller打包程序exe踩过的坑
Nov 19 #Python
基于Python中的yield表达式介绍
Nov 19 #Python
Python函数式编程指南:对生成器全面讲解
Nov 19 #Python
wxPython电子表格功能wx.grid实例教程
Nov 19 #Python
python 实现return返回多个值
Nov 19 #Python
wxPython实现带颜色的进度条
Nov 19 #Python
Python使用Pandas读写Excel实例解析
Nov 19 #Python
You might like
PHP HTML代码串截取代码
2008/12/29 PHP
PHP 引用文件技巧
2010/03/02 PHP
php教程之phpize使用方法
2014/02/12 PHP
Laravel学习教程之从入口到输出过程详解
2017/08/27 PHP
分析php://output和php://stdout的区别
2018/05/06 PHP
Jquery 组合form元素为json格式,asp.net反序列化
2009/07/09 Javascript
ie focus bug 解决方法
2009/09/03 Javascript
jquery的flexigrid无法显示数据提示获取到数据
2013/07/19 Javascript
jQuery中scrollTop()方法用法实例
2015/01/16 Javascript
JS实现点击按钮控制Div变宽、增高及调整背景色的方法
2015/08/05 Javascript
强大的 Angular 表单验证功能详细介绍
2017/05/23 Javascript
JavaScript贪吃蛇小组件实例代码
2017/08/20 Javascript
vue实现提示保存后退出的方法
2018/03/15 Javascript
vue中使用element-ui进行表单验证的实例代码
2018/06/22 Javascript
react-navigation之动态修改title的内容
2018/09/26 Javascript
Vue实现简单计算器案例
2020/02/25 Javascript
wxpython 学习笔记 第一天
2009/02/09 Python
理解python多线程(python多线程简明教程)
2014/06/09 Python
深入讲解Python函数中参数的使用及默认参数的陷阱
2016/03/13 Python
python如何使用unittest测试接口
2018/04/04 Python
Python设计模式之原型模式实例详解
2019/01/18 Python
为什么说Python可以实现所有的算法
2019/10/04 Python
Python实现快速排序的方法详解
2019/10/25 Python
python打开文件的方式有哪些
2020/06/29 Python
在html页面中取得session中的值的方法
2020/08/11 HTML / CSS
Html5页面点击遮罩层背景关闭遮罩层
2020/11/30 HTML / CSS
Eagle Eyes Optics鹰眼光学:高性能太阳镜
2018/12/07 全球购物
CHARLES & KEITH澳大利亚官网:新加坡时尚品牌
2019/01/22 全球购物
美国最大的购物网站:Amazon.com(亚马逊美国)
2020/05/23 全球购物
中文系学生自荐信范文
2013/11/13 职场文书
博士研究生自我鉴定范文
2013/12/04 职场文书
创业计划书如何吸引他人眼球
2014/01/10 职场文书
项目考察欢迎辞
2014/01/17 职场文书
音乐节策划方案
2014/06/09 职场文书
2015年秋季小学开学典礼主持词
2015/07/16 职场文书
SpringBoot 集成Redis 过程
2021/06/02 Redis