Pygame(二十)音樂播放器2
接上節(jié)內(nèi)容:
# /usr/bin/python3
# Author: 愛編程的章老師
# @Time: 2021/1/17 0017
# E-mail: Bluesand2010@163.com
import pygame
import sys
import os
from random import randint
'''音樂播放器'''
# 音樂播放/暫停/繼續(xù)/停止功能
# 實現(xiàn)播放列表顯示功能
# 實現(xiàn)單曲循環(huán)/列表循環(huán)/隨機播放功能
# 實現(xiàn)進度條拖動改變進度功能
# 實現(xiàn)音量調(diào)節(jié)
# 常量申明部分
WINDOW_SIZE = WINDOW_WIDTH, WINDOW_HEIGHT = 500, 300 # 窗體的大小設(shè)置
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():
button_surface.fill("white")
button_surface.blit(prev_img, prev_rect)
if play_flag == 0 or play_flag == 2:
button_surface.blit(play_img, play_rect)
else:
button_surface.blit(pause_img, play_rect)
button_surface.blit(next_img, next_rect)
button_surface.blit(stop_img, stop_rect)
if loop_flag == 0:
button_surface.blit(loop_img, loop_rect)
elif loop_flag == 1:
button_surface.blit(single_loop_img, loop_rect)
elif loop_flag == 2:
button_surface.blit(random_img, loop_rect)
# 畫播放列表
def draw_playlist(music_play = -1):
global music_list
play_list_surface.fill("gray")
for index, music in enumerate(music_list):
if index == music_play:
music_surface = play_list_font.render(music, True, "black", "green")
else:
music_surface = play_list_font.render(music, True, "black")
height = music_surface.get_height()
play_list_surface.blit(music_surface, (10, index * (height+5) + 10))
# 畫播放進度條
def draw_play_progress(mt, val = 1):
play_progress_surface.fill('white')
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(mt, 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):
valume_surface.fill('white')
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))
pygame.display.update()
# 獲取音樂目錄下的所有mp3文件名
def get_all_music():
music_list = []
global music_dir
for root,dirs, files in os.walk(music_dir):
for file in files:
name, extname = os.path.splitext(file)
if extname == ".mp3":
music_list.append((file))
return music_list
# 音樂播放功能
def play_music(num):
pygame.mixer.music.load(music_dir + "/" + music_list[num])
pygame.mixer.music.play()
'''程序主體'''
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, 14)
play_time_font = pygame.font.Font(font_path, 12)
valume_font = pygame.font.Font(font_path, 12)
# 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")
# 按鈕矩形
prev_rect = pygame.Rect((70,1), (BUTTON_SIZE, BUTTON_SIZE))
play_rect = pygame.Rect((85 + BUTTON_SIZE * 1,1), (BUTTON_SIZE, BUTTON_SIZE))
next_rect = pygame.Rect((100 + BUTTON_SIZE * 2,1), (BUTTON_SIZE, BUTTON_SIZE))
stop_rect = pygame.Rect((115 + BUTTON_SIZE * 3,1), (BUTTON_SIZE, BUTTON_SIZE))
loop_rect = pygame.Rect((130 + BUTTON_SIZE * 4,1), (BUTTON_SIZE, BUTTON_SIZE))
value_rect = pygame.Rect(WINDOW_WIDTH//2 , BUTTON_BAR_HEIGHT , WINDOW_WIDTH//2 , PROGRESS_BAR_HEIGHT)
progress_rect = pygame.Rect(0, BUTTON_BAR_HEIGHT, WINDOW_WIDTH//2 , PROGRESS_BAR_HEIGHT)
# 播放列表
music_dir = "/".join([PATH_ROOT, "src/music"])
music_list = get_all_music()
play_list_surface = pygame.Surface((WINDOW_WIDTH, WINDOW_WIDTH - BUTTON_BAR_HEIGHT + PROGRESS_BAR_HEIGHT))
play_list_surface.fill("gray")
# 播放狀態(tài)相關(guān)變量
music_num =-1 # 默認播放第一首歌
play_flag = 0 # 播放狀態(tài): 在播放還是暫停,還是停止
loop_flag = 0 # 循環(huán)狀態(tài):0 列表循環(huán) 1: 單曲循環(huán) 2: 隨機播放
MUSIC_END = pygame.USEREVENT + 1
draw_play_progress("0")
draw_volume_progres(0.5)
draw_buttons()
draw_playlist()
draw_all()
pygame.display.update()
while 1:
# 退出事件檢測
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# 鼠標按鍵響應(yīng)
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = pygame.mouse.get_pos()
# 單擊事件響應(yīng)
if event.button == 1:
# 播放按鈕響應(yīng)
if play_rect.collidepoint(mouse_pos):
if play_flag == 1:
# 播放狀態(tài)時點連暫停安按鈕時切換為暫停狀態(tài)
play_flag = 2
pygame.mixer.music.pause()
elif play_flag == 0:
# 停止狀態(tài)時按播放,切換為播放狀態(tài)
play_flag = 1
music_num = 0
play_music(music_num)
elif play_flag == 2:
play_flag = 1
pygame.mixer.music.unpause()
# 前一首響應(yīng)
elif prev_rect.collidepoint(mouse_pos):
if loop_flag == 2:
# 隨機播放的情況下,下一首哥,將隨機選取
while 1:
temp = randint(0, len(music_list)-1)
if music_num == temp:
continue
music_num = temp
break
else:
music_num -= 1
if music_num < 0:
music_num = len(music_list) - 1
play_music(music_num)
# 后一首響應(yīng)
elif next_rect.collidepoint(mouse_pos):
if loop_flag == 2:
# 隨機播放的情況下,下一首哥,將隨機選取
while 1:
temp = randint(0, len(music_list)-1)
if music_num == temp:
continue
music_num = temp
break
else:
music_num += 1
if music_num > len(music_list) - 1:
music_num = 0
play_music(music_num)
# 循環(huán)按鈕
elif loop_rect.collidepoint(mouse_pos):
loop_flag = (loop_flag + 1) % 3
# 停止按鈕響應(yīng)
elif stop_rect.collidepoint(mouse_pos):
play_flag = 0
music_num = -1
pygame.mixer.music.stop()
# 音量滾輪響應(yīng)
if value_rect.collidepoint(mouse_pos):
# 上滾增加音量
if event.button == 4:
value_num = pygame.mixer.music.get_volume()
if value_num + 0.01 > 1:
value_num = 1
else:
value_num += 0.01
pygame.mixer.music.set_volume(value_num)
# 下滾減少音量
if event.button == 5:
value_num = pygame.mixer.music.get_volume()
if value_num - 0.01 < 0:
value_num = 0
else:
value_num -= 0.01
pygame.mixer.music.set_volume(value_num)
if progress_rect.collidepoint(mouse_pos):
# 上滾增加音量
if event.button == 4:
value_num = pygame.mixer.music.get_volume()
if value_num + 0.01 > 1:
value_num = 1
else:
value_num += 0.01
# 下滾減少音量
if event.button == 5:
value_num = pygame.mixer.music.get_volume()
if value_num - 0.01 < 0:
value_num = 0
else:
value_num -= 0.01
# 一曲完畢事件響應(yīng)
if event.type == MUSIC_END:
if loop_flag == 2:
# 隨機播放的情況下,下一首哥,將隨機選取
while 1:
temp = randint(0, len(music_list) - 1)
if music_num == temp:
continue
music_num = temp
break
elif loop_flag == 0:
music_num += 1
if music_num > len(music_list) - 1:
music_num = 0
play_music(music_num)
music_time = pygame.mixer.music.get_pos()
if music_time < 0:
music_time = 0
s = music_time//1000 % 60
m = music_time//60000
h = music_time//3600000
music_time = str(h).ljust(2, "0") + ":" +str(m).ljust(2, "0") + ":" + str(s).ljust(2, "0") + "." + str((music_time % 1000)//10).ljust(2, "0")
value_num = pygame.mixer.music.get_volume()
draw_buttons()
draw_playlist(music_num)
draw_play_progress(music_time)
draw_volume_progres(value_num)
draw_all()
pygame.time.Clock().tick(10)
文件目錄結(jié)構(gòu):
-
整體結(jié)構(gòu)
image.png -
src 目錄
src目錄 -
fonts目錄
fonts目錄 -
img目錄
img目錄 -
music目錄
music目錄
已完成的功能
- 文件只搜索mp3格式的
- 正常播放,下一首,上一首
- 列表循環(huán), 單曲循環(huán),隨機播放完成
- 音量大小調(diào)節(jié)完成
- 當前播放歌曲列表特殊顯示
- 當前歌曲播放時間功能
待改進功能
- 列表滾動顯示功能
- 歌曲時長功能
- 進度條拖動功能
演示動畫
軟件演示
后記
這么一個300行左右代碼的軟件,對于新入門的朋友來說,其實已經(jīng)有點長了.
代碼還有很多的因為定位的讀者問題, 沒有做太深入的優(yōu)化.
如果需要完整的代碼和相應(yīng)的圖片資源的朋友可以留言微信或者郵箱.看到一律回復(fù)