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()