182 lines
6.5 KiB
Python
182 lines
6.5 KiB
Python
import tkinter
|
|
import pygame
|
|
import time
|
|
import re
|
|
from tkinter import ttk
|
|
|
|
|
|
class MusicPlayer:
|
|
def __init__(self, cls_root):
|
|
# 初始化变量
|
|
self.root = cls_root
|
|
self.progress_bar = None
|
|
self.play_button = None
|
|
self.pause_button = None
|
|
self.music_file = None
|
|
self.music_length = 0
|
|
self.time = None
|
|
self.time_format = "%n/%a"
|
|
self.pause = True
|
|
self.progress = []
|
|
self.length = []
|
|
self.finish = True
|
|
self.d_value = 0.0
|
|
# 初始化 Pygame
|
|
pygame.init()
|
|
# 初始化上次更新的时间
|
|
self.last_update_time = time.time()
|
|
# 开始更新进度条
|
|
self.current_position = 0.0 # 用于跟踪当前音乐播放的位置
|
|
self.update_progress()
|
|
|
|
def load_music(self, music_file):
|
|
self.music_file = music_file
|
|
self.music_length = pygame.mixer.Sound(self.music_file).get_length() # 获取音乐长度
|
|
pygame.mixer.music.load(self.music_file)
|
|
|
|
def bind(self, cls_progress_bar=None, cls_pause_button=None, cls_play_button=None, cls_time=None):
|
|
# 绑定控件
|
|
self.progress_bar = cls_progress_bar
|
|
self.pause_button = cls_pause_button
|
|
self.play_button = cls_play_button
|
|
self.time = cls_time
|
|
|
|
def play_music(self, music_file):
|
|
self.finish = False
|
|
self.load_music(music_file)
|
|
self.d_value = 0.0
|
|
pygame.mixer.music.play()
|
|
self.pause = False
|
|
self.current_position = 0.0
|
|
if self.progress_bar is not None:
|
|
self.progress_bar["from_"] = 0
|
|
self.progress_bar["to"] = float(self.music_length)
|
|
self.progress_bar.set(0)
|
|
|
|
def stop_music(self):
|
|
pygame.mixer.music.stop()
|
|
self.music_file = None
|
|
self.finish = True
|
|
self.pause = True
|
|
self.current_position = 0.0
|
|
self.music_length = 0
|
|
if self.time is not None:
|
|
self.time["text"] = ""
|
|
if self.progress_bar is not None:
|
|
self.progress_bar["from_"] = 0
|
|
self.progress_bar["to"] = 1
|
|
self.progress_bar.set(0)
|
|
|
|
def pause_music(self):
|
|
try:
|
|
if not self.finish:
|
|
if self.pause:
|
|
pygame.mixer.music.unpause()
|
|
self.pause = False
|
|
else:
|
|
pygame.mixer.music.pause()
|
|
self.pause = True
|
|
except:
|
|
self.play_music()
|
|
|
|
def set_progress(self, value):
|
|
if not self.finish:
|
|
# 检查是否距离上次更新超过0.55秒
|
|
if abs(float(value) - self.last_update_time) > 0.55:
|
|
# 将进度条的值直接设置为音乐的播放位置
|
|
self.current_position = float(value)
|
|
self.d_value = float(value) - pygame.mixer.music.get_pos() / 1000
|
|
try:
|
|
pygame.mixer.music.set_pos(float(value))
|
|
except:
|
|
self.stop_music()
|
|
|
|
def update_progress(self):
|
|
self.current_position = pygame.mixer.music.get_pos() / 1000 + self.d_value
|
|
if not self.pause:
|
|
if self.music_file is not None:
|
|
if self.progress_bar is not None:
|
|
# 更新进度条
|
|
self.progress_bar.set(self.current_position)
|
|
self.last_update_time = self.progress_bar.get()
|
|
# 更新播放时长
|
|
if self.time is not None:
|
|
self.time["text"] = self.time_format.replace("%n", self.get_progress()).replace("%a",
|
|
self.get_length())
|
|
# 每隔一段时间再次更新进度条
|
|
self.root.after(500, self.update_progress)
|
|
|
|
def get_busy(self):
|
|
return not self.pause
|
|
|
|
def get_progress(self, state="%m:%s"):
|
|
self.progress = self.get_format(int(self.current_position))
|
|
if len(self.progress[0]) == 1:
|
|
self.progress[0] = "0" + self.progress[0]
|
|
if len(self.progress[1]) == 1:
|
|
self.progress[1] = "0" + self.progress[1]
|
|
if len(self.progress[2]) == 1:
|
|
self.progress[2] = "0" + self.progress[2]
|
|
return_value = state.replace("%s", self.progress[0])
|
|
return_value = return_value.replace("%m", self.progress[1])
|
|
return_value = return_value.replace("%h", self.progress[2])
|
|
return return_value
|
|
|
|
@staticmethod
|
|
def get_format(value):
|
|
second = value % 60
|
|
minute = value // 60 % 60
|
|
hour = value // 3600
|
|
return [str(second), str(minute), str(hour)]
|
|
|
|
@staticmethod
|
|
def decode_format(value):
|
|
match = re.match(r'(\d+):(\d)', value)
|
|
if match:
|
|
minute = int(match.group(1))
|
|
second = int(match.group(2))
|
|
timestamp = minute * 60 + second
|
|
return timestamp
|
|
else:
|
|
return None
|
|
|
|
def get_length(self, state="%m:%s"):
|
|
self.length = self.get_format(int(self.music_length))
|
|
if len(self.length[0]) == 1:
|
|
self.length[0] = "0" + self.length[0]
|
|
if len(self.length[1]) == 1:
|
|
self.length[1] = "0" + self.length[1]
|
|
if len(self.length[2]) == 1:
|
|
self.length[2] = "0" + self.length[2]
|
|
return_value = state.replace("%s", self.length[0])
|
|
return_value = return_value.replace("%m", self.length[1])
|
|
return_value = return_value.replace("%h", self.length[2])
|
|
return return_value
|
|
|
|
def set_format_of_time(self, cls_format="%n/%a"):
|
|
self.time_format = cls_format
|
|
|
|
def get_finished(self):
|
|
return self.finish
|
|
|
|
|
|
if __name__ == "__main__":
|
|
root = tkinter.Tk()
|
|
player = MusicPlayer(root)
|
|
root.title("音乐播放器")
|
|
progress_bar = ttk.Scale(root, orient="horizontal", from_=0, to=player.music_length, length=2000)
|
|
progress_bar.pack()
|
|
pause_button = ttk.Button(root, text="暂停", command=player.pause_music)
|
|
play_button = ttk.Button(root, text="播放", command=lambda: player.play_music("your_music_file.mp3"))
|
|
stop_button = ttk.Button(root, text="停止", command=player.stop_music)
|
|
pause_button.pack()
|
|
play_button.pack()
|
|
stop_button.pack()
|
|
progress_time = ttk.Label(root, text="")
|
|
progress_time.pack()
|
|
progress_bar["command"] = lambda event: player.set_progress(progress_bar.get())
|
|
player.bind(progress_bar, pause_button, play_button, progress_time)
|
|
player.set_format_of_time()
|
|
|
|
root.mainloop()
|