Pygame(十九)音樂播放器1
前情提要
在這里插入圖片描述
本節(jié)提要
界成設計
效果圖
在這里插入圖片描述
界面代碼設計
# /usr/bin/python3
# Author: 愛編程的章老師
# @Time: 2021/1/17 0017
# E-mail: Bluesand2010@163.com
import pygame
import sys
import os
'''音樂播放器'''
# 音樂播放/暫停/繼續(xù)/停止功能
# 實現(xiàn)播放列表顯示功能
# 實現(xiàn)單曲循環(huán)/列表循環(huán)/隨機播放功能
# 實現(xiàn)進度條拖動改變進度功能
# 實現(xiàn)音量調節(jié)
# 常量申明部分
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"]) # 循環(huán)播放按鈕圖片路徑
SINGLE_LOOP_IMG_PATH = "/".join([PATH_ROOT, "src/img/loop1.png"]) # 循環(huán)播放按鈕圖片路徑
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 # 按鈕的大小
# 功能實現(xiàn)部分
# 畫按鈕
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()
代碼分析
這次的代碼比較長
為了使的各功能模塊比較清晰,這里將繪制不同區(qū)域的繪制過程都獨立出來了.這里對這些繪制及相關的設置給出一些必要的解釋說明
常量設置
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"]) # 循環(huán)播放按鈕圖片路徑
SINGLE_LOOP_IMG_PATH = "/".join([PATH_ROOT, "src/img/loop1.png"]) # 循環(huán)播放按鈕圖片路徑
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 # 按鈕的大小
- 播放器的窗口大小
- 程序所在的目錄
- 3-9: 相關按鈕的圖片文件路徑
- 按鈕條的高度
- 進度條的高度
- 按鈕大小
這些量設置成變量, 是方便后續(xù)調與修改
按鈕區(qū)
第一個步驟:加載圖片,生成圖片surface對象
第二個步驟:將surface對象貼(blit)到按鈕區(qū)上去
加載圖像,也可以獨立成函數(shù)
# 圖片加載
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))
這里將貼上去設置成函數(shù) ,是因為在后期的運時,需要切換按鈕的狀態(tài),要重新繪圖
播放/暫停 相互切換
全局循環(huán)/單曲循環(huán)/隨機播放 相互切換
進度條
# 畫播放進度條
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))
音量條
音量與進度條基本相同,只是鏡象繪制
后記
今天的內容對繪圖的知識要求比較高
如果有不是很清楚的地方,建議好好翻翻過去的內容,或者留言給我.