侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

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

Python  /  管理员 发布于 5年前   709

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 = Falseis_kuaijin = False# 记录开始时间start_time = time.time()# 暂停时长置为0pause_start_time = pause_end_time = pause_duration_time = 0# 进度条开始位置置为40begin_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 = Falseis_kuaijin = False# 记录开始时间start_time = time.time()# 暂停时长置为0pause_start_time = pause_end_time = pause_duration_time =0# 进度条开始位置置为40begin_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、效果图

刺猬牛逼!!!

4、完整代码

#-*- coding: utf-8 -*-import os,time,sysfrom sys import exitimport pygamefrom pygame.locals import *from mutagen.mp3 import MP3from random import choicedef 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_timepause_start_time =0pause_end_time =0pause_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 musicsmusics = 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 = Falseis_kuaijin = False# 记录开始时间start_time = time.time()# 暂停时长置为0pause_start_time = pause_end_time = pause_duration_time = 0# 进度条开始位置置为40begin_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 = Falseis_kuaijin = False# 记录开始时间start_time = time.time()# 暂停时长置为0pause_start_time = pause_end_time = pause_duration_time =0# 进度条开始位置置为40begin_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踩过的坑

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


  • 上一条:
    Pycharm创建项目时如何自动添加头部信息
    下一条:
    pyinstaller打包程序exe踩过的坑
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客