小案例:用Python制作音乐播放器2.0

朋友们大家好!

我们在之前就已经完成过一个简易的音乐播放器,但它也有许多需要完善的地方:

        1.  没有进度条,无法得知和调整歌曲进度。

        2.  音乐播放完后就结束了,不会重复播放或是切换下一个。

        3.  界面颜色过于单调。

那么,在文章中将会改进这些缺点。

 这张图片是改进后的结果:

 


1. 增加进度条

首先需要获取播放音频长度的功能。

在这里我们使用Python第三方库 eyed3 里面的 load 函数。

from eyed3 import load

music = load("音频文件路径")
print(music.info.time_secs) # 该属性可以获取音频的长度(单位: 秒)

我们就可以写一个函数来获取音频长度

def getLength(music, all_music, all_music_path): # 获取音乐时长
    music = load(all_music_path[all_music.index(music)])
    return music.info.time_secs

用变量存储音频播放时间

我们可以定义一个 time 变量来存储音频播放的时间,当开始播放音频时先将 time 赋值为0

 如何让窗口上的进度条时刻更新 time 变量的值呢?

我们可以在 window.read() 里面添加一个参数 timeout,这样就可以每隔 timeout 毫秒 执行一次窗口事件处理。

window = Window(...)

while 1:
    event, values = window.read(timeout = 100) # 这里表示每隔 100 毫秒执行一次读取
    ...    

最后我们在循环中增加 time 变量,在窗口中更新进度即可。


2. 添加音乐播放模式

我们可以定义一个变量来存储当前播放的模式。

play_setting = 'Loop'  # 循环播放: Loop  重复播放: Repeat

 然后在窗口上添加菜单,用于设置播放模式。

然后再事件处理里面增加条件判断。

if event == '重复播放':
        play_setting = 'Repeat'
if event == '循环播放':
    play_setting = 'Loop'

3. 界面设置

在 PySimpleGUI 中可以通过 theme() 函数 设置窗口主题

import PySimpleGUI as sg

# 在这里使用 LightGray1 主题
# 注: 如果填入的主题不存在,PySimpleGUI 会随机抽取一个主题
sg.theme("LightGray1")

 


最后在循环中添加以下代码以用于处理进度条拖动等以上功能。

if mixer.music.get_busy():
        time += 0.1               # 将 time 变量的值加 0.1 秒

else:
    if music != '' and (not pause):
        if not len(values['-music_list-']):
            continue
        time = 0
        if play_setting == 'Loop':
            choice_index += 1
            # 如果索引大于音乐项目数则要从第一项开始播放
            if choice_index == len(all_music):
                choice_index = 0
            LoadMusic(all_music[choice_index], all_music, all_music_path)
            
            # 获取音乐信息变量
            length = getLength(music, all_music, all_music_path)

            # 播放进度条修改时长
            window['-rate-'].update(0, range = [0, length])

            window['-music_list-'].update(all_music, scroll_to_index = choice_index, set_to_index = choice_index) # 更新屏幕选择音乐
            
            window['-playing-'].update(showMusic(all_music[choice_index])) # 显示正在播放的音乐

        else:
            LoadMusic(music, all_music, all_music_path)
            
        mixer.music.play()

if event == '-rate-':
    if mixer.music.get_busy():
        # 如果用户拖动则要更新 time 变量和屏幕上的进度条
        mixer.music.set_pos(values['-rate-'])
        time = values['-rate-']

以下就是全部代码:

​
from pygame import mixer
from PySimpleGUI import Window, Slider, B, T, LB, Frame, Menu, popup, theme, popup_get_folder
from os import listdir
from eyed3 import load
from time import sleep

def tip():
    print()
    print('=' * 45)
    for i in ['', '提示:', '    1. 该音乐播放器仅支持 MP3 格式。', '', '    2. 该音乐播放器只能播放计算机上', '       的音频。', '    ', '    3. 添加音乐需要选择含有音乐的', '       文件夹, 这样程序会从该文件', '       夹中筛选出音频添加到音乐列', '       表中。', '', '    4. 由于该播放器音量较大, 播放', '       音乐音量建议在 20% - 30%之间。', '', '感谢用户的支持!', '']:
        print(i)
        sleep(0.05)
    print('=' * 45)
    print()

def getLength(music, all_music, all_music_path): # 获取音乐时长
    music = load(all_music_path[all_music.index(music)])
    return music.info.time_secs

def showMusic(music):
    if len(music) > 23:
        return '正在播放: {}...'.format(music[:23])
    else:
        return '正在播放: {}'.format(music)

def LoadMusic(music, all_music, all_music_path):        # 加载音乐函数
    global time, window

    # 加载音乐
    mixer.music.load(all_music_path[all_music.index(music)])
    time = 0
    

theme('LightGray1')

mixer.init()
mixer.music.set_volume(1)

all_music = []      # 全部音乐名称
all_music_path = [] # 全部音乐对应路径
play_setting = 'Loop'  # 循环播放: Loop  重复播放: Repeat

layout = [
    [Menu([
        ['操作', ['清空列表', '---', '退出']], 
        ['播放设置', ['重复播放', '循环播放']]
        ])], 
    [Frame('播放列表', 
           [
                [T('音频播放列表', font = ('楷体', 15))], 
                [LB(all_music, size = (40, 10), key = '-music_list-', font = ('黑体', 13))], 
                [T('正在播放: 空', font = ('楷体', 12), key = '-playing-')]
            ], font = ('楷体', 16), grab = True )], 
    [T('音量设置', font = ('楷体', 14)), Slider(range = [0, 100], key = '-volume-', default_value = 100, orientation = 'h', enable_events = 1, resolution = 5, size = [23, 20])], 
    [T('播放进度', font = ('楷体', 14)), Slider(range = [0, 100], key = '-rate-', default_value = 100, orientation = 'h', enable_events = 1, size = [23, 20])], 
    [B('添加音频', font = ('楷体', 14)), 
     B('开始播放', font = ('楷体', 14), bind_return_key = True), 
     B('暂停', font = ('楷体', 14))]
    ]

tip()

window = Window('音乐播放器', layout)
pause = False   # 标记是否暂停的变量
choice = ''
music = ''
time = 0         # 音频播放进度变量
choice_index = 0 # 音频选择的索引变量
length = 1.1

while 1:
    event, values = window.read(timeout = 100)
    
    window['-rate-'].update(time) # 每次更新 time 变量

    if event in (None, '退出'):
        mixer.music.stop() #结束所有播放
        break
    
    if event == '重复播放':
        play_setting = 'Repeat'
    if event == '循环播放':
        play_setting = 'Loop'
    
    if mixer.music.get_busy():
        time += 0.1               # 将 time 变量的值加 0.1 秒

    else:
        if music != '' and (not pause):
            if not len(values['-music_list-']):
                continue
            time = 0
            if play_setting == 'Loop':
                choice_index += 1
                # 如果索引大于音乐项目数则要从第一项开始播放
                if choice_index == len(all_music):
                    choice_index = 0
                LoadMusic(all_music[choice_index], all_music, all_music_path)
                
                # 获取音乐信息变量
                length = getLength(music, all_music, all_music_path)

                # 播放进度条修改时长
                window['-rate-'].update(0, range = [0, length])

                window['-music_list-'].update(all_music, scroll_to_index = choice_index, set_to_index = choice_index) # 更新屏幕选择音乐
                
                window['-playing-'].update(showMusic(all_music[choice_index])) # 显示正在播放的音乐

            else:
                LoadMusic(music, all_music, all_music_path)
                
            mixer.music.play()

    if event == '-rate-':
        if mixer.music.get_busy():
            # 如果用户拖动则要更新 time 变量和屏幕上的进度条
            mixer.music.set_pos(values['-rate-'])
            time = values['-rate-']

    elif event == '清空列表':
        all_music.clear()
        all_music_path.clear()
        window['-music_list-'].update(all_music)

    elif event == '-volume-':
        mixer.music.set_volume(values['-volume-'] / 100)
    
    elif event == '开始播放':
        music = values['-music_list-']
        
        if pause:
            music = music[0]
            
            # 如果音乐暂停重新开始后切换了音乐则要重新加载
            if music != choice:
                choice = music
                LoadMusic(music, all_music, all_music_path)

                choice_index = all_music.index(music)
            
                try:
                    # 获取音乐信息变量
                    length = getLength(music, all_music, all_music_path)

                    # 播放进度条修改时长
                    window['-rate-'].update(0, range = [0, length])
                
                    mixer.music.play()
                except:
                    # 如果音频无法播放就应该从列表里删除该音乐
                    all_music_path.pop(choice_index)
                    all_music.remove(music)
                    popup('音频解析错误或音频格式错误', font = '楷体 14', title = '播放错误')

                    window['-music_list-'].update(all_music)
                    music = ''

                else:
                    window['-playing-'].update(showMusic(music)) # 显示正在播放的音乐
                
            # 如果没有切换就继续播放
            else:
                mixer.music.unpause() #继续播放
                pause = False

        else:
            # 如果音乐列表为空, 则不播放音乐
            if len(music) == 0:continue
            
            music = music[0]
            choice = music
            LoadMusic(music, all_music, all_music_path)

            choice_index = all_music.index(music)
            
            try:
                # 获取音乐信息变量
                length = getLength(music, all_music, all_music_path)
                
                # 播放进度条修改时长
                window['-rate-'].update(0, range = [0, length])
                
                mixer.music.play()
            except:
                # 如果音频无法播放就应该从列表里删除该音乐
                all_music_path.pop(choice_index)
                all_music.remove(music)
                popup('音频解析错误或音频格式错误', font = '楷体 14', title = '播放错误')
                
                window['-music_list-'].update(all_music)
                music = ''
            else:
                window['-playing-'].update(showMusic(music)) # 显示正在播放的音乐

            
    elif event == '添加音频':
        music_file = popup_get_folder('打开音频文件夹', no_window = True)  # 打开文件夹获取音频
        if music_file == '':continue
        files = [music_file + '\\' + i for i in listdir(music_file) if i.endswith('.mp3')]
        all_music_path.extend(files)               # 从文件夹中筛选出音频并加入路径
        all_music.extend([i.split('\\')[-1] for i in files])  # 要在屏幕上显示的音乐名
        window['-music_list-'].update(all_music, set_to_index = choice_index, scroll_to_index = choice_index)   # 从屏幕上显示
        
    elif event == '暂停':
        # 如果正在播放
        if mixer.music.get_busy():
            mixer.music.pause() # 暂停
            pause = True        # 更新 pause 变量
    
window.close()

​

 以上就是全部内容,感谢大家观看!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值