Pygame(十九)音乐播放器1

Pygame(十九)音乐播放器1

前情提要

在这里插入图片描述

本节提要

界成设计
效果图
在这里插入图片描述

界面代码设计

# /usr/bin/python3

# Author: 爱编程的章老师
# @Time: 2021/1/17 0017
# E-mail: [email protected]

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))

音量条

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

后记

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

猜你喜欢

转载自blog.csdn.net/weixin_41810846/article/details/112757299