Pygame(十九)音樂播放器1

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  # 按鈕的大小
  1. 播放器的窗口大小
  2. 程序所在的目錄
  3. 3-9: 相關按鈕的圖片文件路徑
  4. 按鈕條的高度
  5. 進度條的高度
  6. 按鈕大小

這些量設置成變量, 是方便后續(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))

音量條

音量與進度條基本相同,只是鏡象繪制

后記

今天的內容對繪圖的知識要求比較高
如果有不是很清楚的地方,建議好好翻翻過去的內容,或者留言給我.

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末碟婆,一起剝皮案震驚了整個濱河市产喉,隨后出現(xiàn)的幾起案子拷泽,更是在濱河造成了極大的恐慌州邢,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辙诞,死亡現(xiàn)場離奇詭異辙售,居然都是意外死亡,警方通過查閱死者的電腦和手機飞涂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門旦部,熙熙樓的掌柜王于貴愁眉苦臉地迎上來祈搜,“玉大人,你說我怎么就攤上這事士八∝参剩” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵曹铃,是天一觀的道長。 經(jīng)常有香客問我捧杉,道長陕见,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任味抖,我火速辦了婚禮评甜,結果婚禮上,老公的妹妹穿的比我還像新娘仔涩。我一直安慰自己忍坷,他們只是感情好,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布熔脂。 她就那樣靜靜地躺著佩研,像睡著了一般。 火紅的嫁衣襯著肌膚如雪霞揉。 梳的紋絲不亂的頭發(fā)上旬薯,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音适秩,去河邊找鬼绊序。 笑死,一個胖子當著我的面吹牛秽荞,可吹牛的內容都是我干的骤公。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼扬跋,長吁一口氣:“原來是場噩夢啊……” “哼阶捆!你這毒婦竟也來了?” 一聲冷哼從身側響起钦听,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤趁猴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后彪见,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體儡司,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年余指,在試婚紗的時候發(fā)現(xiàn)自己被綠了捕犬。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片跷坝。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖碉碉,靈堂內的尸體忽然破棺而出柴钻,到底是詐尸還是另有隱情,我是刑警寧澤垢粮,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布贴届,位于F島的核電站,受9級特大地震影響蜡吧,放射性物質發(fā)生泄漏毫蚓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一昔善、第九天 我趴在偏房一處隱蔽的房頂上張望元潘。 院中可真熱鬧,春花似錦君仆、人聲如沸翩概。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钥庇。三九已至,卻和暖如春咖摹,著一層夾襖步出監(jiān)牢的瞬間上沐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工楞艾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留参咙,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓硫眯,卻偏偏與公主長得像蕴侧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子两入,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內容