Pygame(十九)音乐播放器1

Pygame(十九)音乐播放器1

前情提要

在这里插入图片描述

本节提要

界成设计
效果图


在这里插入图片描述

界面代码设计

# /usr/bin/python3

# Author: 爱编程的章老师
# @Time: 2021/1/17 0017
# E-mail: Bluesand2010@163.com

import pygame
import sys
import os

'''音乐播放器'''
# 音乐播放/暂停/继续/停止功能
# 实现播放列表显示功能
# 实现单曲循环/列表循环/随机播放功能
# 实现进度条拖动改变进度功能
# 实现音量调节




# 常量申明部分
WINDOW_SIZE = WINDOW_WIDTH, WINDOW_HEIGHT = 500, 300  # 窗体的大小设置
PATH_ROOT = os.path.split(sys.argv[0])[0]
PLAY_IMG_PATH = "/".join([PATH_ROOT, "src/img/play.png"])  # 播放按钮图片路径
PAUSE_IMG_PATH = "/".join([PATH_ROOT, "src/img/pause.png"])  # 暂停播放按钮图片路径
LOOP_IMG_PATH = "/".join([PATH_ROOT, "src/img/lOOP.png"])  # 循环播放按钮图片路径
SINGLE_LOOP_IMG_PATH = "/".join([PATH_ROOT, "src/img/loop1.png"])  # 循环播放按钮图片路径
STOP_IMG_PATH = "/".join([PATH_ROOT, "src/img/stop.png"])  # 停止播放按钮图片路径
NEXT_IMG_PATH = "/".join([PATH_ROOT, "src/img/next.png"])  # 后一曲与前一按钮图片路径
RANDOM_IMG_PATH = "/".join([PATH_ROOT, "src/img/random.png"])  # 随机播放钮图片路径
BUTTON_BAR_HEIGHT = 60  # 按钮条的高度
PROGRESS_BAR_HEIGHT = 30  # 进度条的高度
BUTTON_SIZE = 58  # 按钮的大小

# 功能实现部分
# 画按钮
def draw_buttons(play_flag = False, loop_flag = 0):
    button_surface.blit(prev_img, (100, 1))
    if play_flag:
        button_surface.blit(play_img, (100 + BUTTON_SIZE, 1))
    else:
        button_surface.blit(pause_img, (100 + BUTTON_SIZE, 1))
    button_surface.blit(next_img, (100 + BUTTON_SIZE * 2, 1))
    button_surface.blit(stop_img, (100 + BUTTON_SIZE * 3, 1))
    if loop_flag == 0:
        button_surface.blit(loop_img, (100 + BUTTON_SIZE * 4, 1))
    elif loop_flag == 1:
        button_surface.blit(single_loop_img, (100 + BUTTON_SIZE * 4, 1))
    elif loop_flag == 2:
        button_surface.blit(random_img, (100 + BUTTON_SIZE * 4, 1))


# 画播放列表
def draw_playlist(prev="", play_name= "", next=""):
    ...

# 画播放进度条
def draw_play_progress(val = 0.5):
    rect_all = pygame.Rect(5, 5, 290, 20)
    rect_played = pygame.Rect(5, 5, int(290 * val), 20)
    pygame.draw.rect(play_progress_surface, "gray", rect_all)
    pygame.draw.rect(play_progress_surface, "pink", rect_played)
    play_time_font_surface = play_time_font.render("val", True, "red")
    width, height = play_time_font_surface.get_size()
    left = WINDOW_WIDTH//4 - width//2
    top = PROGRESS_BAR_HEIGHT//2 - height//2
    play_progress_surface.blit(play_time_font_surface, (left, top))
    
# 画音量条
def draw_volume_progres(val = 0.5):
    rect_all = pygame.Rect(5, 5, 290, 20)
    rect_played = pygame.Rect(295 - int(290 * val), 5, int(290 * val), 20)
    pygame.draw.rect(valume_surface, "gray", rect_all)
    pygame.draw.rect(valume_surface, "pink", rect_played)
    volume_font_surface = valume_font.render("val", True, "red")
    width, height = volume_font_surface.get_size()
    left = WINDOW_WIDTH//4 - width//2
    top = PROGRESS_BAR_HEIGHT//2 - height//2
    valume_surface.blit(volume_font_surface, (left, top))

## 绘制四个版块的内容
def draw_all():
    screen.blit(button_surface,(0,0))
    screen.blit(play_progress_surface,(0, BUTTON_BAR_HEIGHT))
    screen.blit(valume_surface, (WINDOW_WIDTH//2, BUTTON_BAR_HEIGHT))
    screen.blit(play_list_surface, (0, BUTTON_BAR_HEIGHT + PROGRESS_BAR_HEIGHT))


print(PATH_ROOT)


'''程序主体'''
pygame.init()
screen = pygame.display.set_mode(WINDOW_SIZE)
pygame.display.set_caption("简单音乐播放器 by 爱编程的章老师")


# 图片加载
play_img = pygame.image.load(PLAY_IMG_PATH).convert_alpha()
pause_img = pygame.image.load(PAUSE_IMG_PATH).convert_alpha() 
stop_img = pygame.image.load(STOP_IMG_PATH).convert_alpha() 
prev_img = pygame.image.load(NEXT_IMG_PATH).convert_alpha()
loop_img = pygame.image.load(LOOP_IMG_PATH).convert_alpha() 
single_loop_img = pygame.image.load(SINGLE_LOOP_IMG_PATH).convert_alpha() 
random_img = pygame.image.load(RANDOM_IMG_PATH).convert_alpha() 

# 放缩图片大小
play_img = pygame.transform.scale(play_img, (BUTTON_SIZE,BUTTON_SIZE))
pause_img = pygame.transform.scale(pause_img, (BUTTON_SIZE,BUTTON_SIZE))
stop_img = pygame.transform.scale(stop_img, (BUTTON_SIZE,BUTTON_SIZE))
prev_img = pygame.transform.scale(prev_img, (BUTTON_SIZE,BUTTON_SIZE))
next_img = pygame.transform.flip(prev_img, True,False)

loop_img = pygame.transform.scale(loop_img, (BUTTON_SIZE,BUTTON_SIZE))
single_loop_img = pygame.transform.scale(single_loop_img, (BUTTON_SIZE,BUTTON_SIZE))
random_img = pygame.transform.scale(random_img, (BUTTON_SIZE,BUTTON_SIZE))



# 字体工具
# 字体路径
font_path = "/".join([PATH_ROOT, "src/fonts/msyh.ttf"])

# 字体对象
play_list_font = pygame.font.Font(font_path, 12)
play_time_font = pygame.font.Font(font_path, 10)
valume_font = pygame.font.Font(font_path, 10)

# surface 对象
# 按钮条surface
button_surface = pygame.Surface((WINDOW_WIDTH, BUTTON_BAR_HEIGHT))
button_surface.fill("white")
# # 播放进度条
play_progress_surface = pygame.Surface((WINDOW_WIDTH//2, PROGRESS_BAR_HEIGHT))
play_progress_surface.fill("white")
# # 音量条
valume_surface = pygame.Surface((WINDOW_WIDTH //2, PROGRESS_BAR_HEIGHT))
valume_surface.fill("white")


# 播放列表
play_list_surface = pygame.Surface((WINDOW_WIDTH, WINDOW_WIDTH - BUTTON_BAR_HEIGHT + PROGRESS_BAR_HEIGHT))
play_list_surface.fill("yellow")

draw_buttons()
draw_all()
pygame.display.update()
while 1:
    # 退出事件检测
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

代码分析

这次的代码比较长
为了使的各功能模块比较清晰,这里将绘制不同区域的绘制过程都独立出来了.这里对这些绘制及相关的设置给出一些必要的解释说明

常量设置

WINDOW_SIZE = WINDOW_WIDTH, WINDOW_HEIGHT = 500, 300  # 窗体的大小设置
PATH_ROOT = os.path.split(sys.argv[0])[0]
PLAY_IMG_PATH = "/".join([PATH_ROOT, "src/img/play.png"])  # 播放按钮图片路径
PAUSE_IMG_PATH = "/".join([PATH_ROOT, "src/img/pause.png"])  # 暂停播放按钮图片路径
LOOP_IMG_PATH = "/".join([PATH_ROOT, "src/img/lOOP.png"])  # 循环播放按钮图片路径
SINGLE_LOOP_IMG_PATH = "/".join([PATH_ROOT, "src/img/loop1.png"])  # 循环播放按钮图片路径
STOP_IMG_PATH = "/".join([PATH_ROOT, "src/img/stop.png"])  # 停止播放按钮图片路径
NEXT_IMG_PATH = "/".join([PATH_ROOT, "src/img/next.png"])  # 后一曲与前一按钮图片路径
RANDOM_IMG_PATH = "/".join([PATH_ROOT, "src/img/random.png"])  # 随机播放钮图片路径
BUTTON_BAR_HEIGHT = 60  # 按钮条的高度
PROGRESS_BAR_HEIGHT = 30  # 进度条的高度
BUTTON_SIZE = 58  # 按钮的大小
  1. 播放器的窗口大小
  2. 程序所在的目录
  3. 3-9: 相关按钮的图片文件路径
  4. 按钮条的高度
  5. 进度条的高度
  6. 按钮大小

这些量设置成变量, 是方便后续调与修改

按钮区

第一个步骤:加载图片,生成图片surface对象
第二个步骤:将surface对象贴(blit)到按钮区上去
加载图像,也可以独立成函数

# 图片加载
play_img = pygame.image.load(PLAY_IMG_PATH).convert_alpha()
pause_img = pygame.image.load(PAUSE_IMG_PATH).convert_alpha() 
stop_img = pygame.image.load(STOP_IMG_PATH).convert_alpha() 
prev_img = pygame.image.load(NEXT_IMG_PATH).convert_alpha()
loop_img = pygame.image.load(LOOP_IMG_PATH).convert_alpha() 
single_loop_img = pygame.image.load(SINGLE_LOOP_IMG_PATH).convert_alpha() 
random_img = pygame.image.load(RANDOM_IMG_PATH).convert_alpha() 

# 放缩图片大小
play_img = pygame.transform.scale(play_img, (BUTTON_SIZE,BUTTON_SIZE))
pause_img = pygame.transform.scale(pause_img, (BUTTON_SIZE,BUTTON_SIZE))
stop_img = pygame.transform.scale(stop_img, (BUTTON_SIZE,BUTTON_SIZE))
prev_img = pygame.transform.scale(prev_img, (BUTTON_SIZE,BUTTON_SIZE))
next_img = pygame.transform.flip(prev_img, True,False)

loop_img = pygame.transform.scale(loop_img, (BUTTON_SIZE,BUTTON_SIZE))
single_loop_img = pygame.transform.scale(single_loop_img, (BUTTON_SIZE,BUTTON_SIZE))
random_img = pygame.transform.scale(random_img, (BUTTON_SIZE,BUTTON_SIZE))

贴上去:

def draw_buttons(play_flag = False, loop_flag = 0):
    button_surface.blit(prev_img, (100, 1))
    if play_flag:
        button_surface.blit(play_img, (100 + BUTTON_SIZE, 1))
    else:
        button_surface.blit(pause_img, (100 + BUTTON_SIZE, 1))
    button_surface.blit(next_img, (100 + BUTTON_SIZE * 2, 1))
    button_surface.blit(stop_img, (100 + BUTTON_SIZE * 3, 1))
    if loop_flag == 0:
        button_surface.blit(loop_img, (100 + BUTTON_SIZE * 4, 1))
    elif loop_flag == 1:
        button_surface.blit(single_loop_img, (100 + BUTTON_SIZE * 4, 1))
    elif loop_flag == 2:
        button_surface.blit(random_img, (100 + BUTTON_SIZE * 4, 1))

这里将贴上去设置成函数 ,是因为在后期的运时,需要切换按钮的状态,要重新绘图
播放/暂停 相互切换
全局循环/单曲循环/随机播放 相互切换

进度条

# 画播放进度条
def draw_play_progress(val):
    rect_all = pygame.Rect(5, 5, 290, 20)  # 底色矩形
    rect_played = pygame.Rect(5, 5, int(290 * val), 20)
    pygame.draw.rect(play_progress_surface, "gray", rect_all)
    pygame.draw.rect(play_progress_surface, "pink", rect_played)
    play_time_font_surface = play_time_font.render("val", True, "red")
    width, height = play_time_font_surface.get_size()
    left = WINDOW_WIDTH//4 - width//2
    top = PROGRESS_BAR_HEIGHT//2 - height//2
    play_progress_surface.blit(play_time_font_surface, (left, top))

进度条分成三部分:
底色部分

    rect_all = pygame.Rect(5, 5, 290, 20)  # 底色矩形

进度部分:

    rect_played = pygame.Rect(5, 5, int(290 * val), 20)  # 进度部分

播放时长显示:

    play_time_font_surface = play_time_font.render("val", True, "red")
    width, height = play_time_font_surface.get_size()
    left = WINDOW_WIDTH//4 - width//2
    top = PROGRESS_BAR_HEIGHT//2 - height//2
    play_progress_surface.blit(play_time_font_surface, (left, top))

音量条

音量与进度条基本相同,只是镜象绘制

后记

今天的内容对绘图的知识要求比较高
如果有不是很清楚的地方,建议好好翻翻过去的内容,或者留言给我.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容