python tkinter音乐播放器

问题遇到的现象和发生背景

代码运行时会异常退出

用代码块功能插入代码,请勿粘贴截图
    self.filebox = []  # 存放歌曲文件夹路径
    self.filepath = []  # 存放歌曲路径
    self.filename = []  # 存放音乐名称
    self.playing = False  # 是否正在播放
    self.get_mouse = True  # 鼠标单击播放
    self.num = 0  # 正在播放音乐的ID
    self.vol = 100  # 音量控制,默认为100
    self.botton_active = 'disable'
    self.flag = None  # 进度条控制
    self.mode_choose = ''  # 模式选择,默认为顺序播放
    self.default_mode = '顺序播放'  # 默认模式
    self.muted = True  # 静音标志
    self.value = 100  # 获取暂停时的音量, 默认为100
    self.total_length = 0  # 总时长
    self.music_path = ""  # 单首歌路径
    self.current_time = None
    self.tag = False  # 是否按了上/下一首和暂停
    self.now_time = 0  # 当前时长
    self.mark = False  # 是否操作了上/下一首

    self.lb = None  # Listbox存放音乐
    self.play_state = None  # 播放状态
    self.musicName = None  # 当前播放的音乐
    self.pause_resume = None  # 暂停/播放设置

    # 按钮  (按钮图片路径)
    self.botton_Next_Music = None
    self.Next_photo = PhotoImage(file='E:/Py File/音乐组件/下一首.png')

    self.botton_Music_pause = None
    self.play_photo = PhotoImage(file='E:/Py File/音乐组件/播放.png')
    self.pause_photo = PhotoImage(file='E:/Py File/音乐组件/暂停.png')

    self.botton_Stop_Music = None
    self.stop_photo = PhotoImage(file='E:/Py File/音乐组件/停止.png')

    self.botton_Up_Music = None
    self.Up_photo = PhotoImage(file='E:/Py File/音乐组件/上一首.png')

    self.botton_Music_delete = None
    self.delete_photo = PhotoImage(file='E:/Py File/音乐组件/删除.png')
    self.add_photo = PhotoImage(file='E:/Py File/音乐组件/打开.png')

    self.botton_control_voice = None
    self.voice_play_photo = PhotoImage(file='E:/Py File/音乐组件/音量.png')
    self.voice_mult_photo = PhotoImage(file='E:/Py File/音乐组件/静音.png')

    self.optionals_order_photo = PhotoImage(file='E:/Py File/音乐组件/顺序播放.png')
    self.optionals_circle_photo = PhotoImage(file='E:/Py File/音乐组件/循环播放.png')
    self.optionals_rant_photo = PhotoImage(file='E:/Py File/音乐组件/随机播放.png')

    # 对应组件
    self.main_Bottons()

def mult(self):  # 静音完成
    if self.muted:  # True可以静音 False表示恢复音量
        self.muted = False
        self.value_botton['image'] = self.voice_mult_photo
        self.control_voice(0)
        self.botton_control_voice.set(0)
    else:
        self.value_botton['image'] = self.voice_play_photo
        self.control_voice(self.value)
        self.botton_control_voice.set(self.value)
        self.muted = True

def control_voice(self, value):  # 音量控制完成
    self.vol = value
    if self.muted:
        self.value = value
    try:
        val = float(self.vol) / 100
        pygame.mixer.music.set_volume(val)
    except Exception:
        pass

def get_length(self):  # 获取音乐时长完成
    index = self.filename.index(self.musicName)
    self.music_path = self.filepath[index]

    total = pygame.mixer.Sound(self.music_path)
    self.total_length = total.get_length()
    mins, secs = divmod(self.total_length, 60)
    mins = round(mins)
    secs = round(secs)
    timeformat = '0{}:{}'.format(mins, secs)
    self.length_label['text'] = "总时长" + ': ' + str(timeformat)
    # self.now_time = 0
    t1 = threading.Thread(target=self.get_current_time, args=(self.total_length,))
    t1.start()

def get_current_time(self, length):  # 播放进度完成
    condition = self.playing and length > self.now_time and self.tag is False
    while condition:
        if self.pause_resume.get() == '暂停':
            time.sleep(1)
            self.now_time += 1
            if self.now_time >= 60:
                now_time_mins, now_time_secs = divmod(self.now_time, 60)
                now_time_mins = round(now_time_mins)
                now_time_secs = round(now_time_secs)
                self.current_time['text'] = "播放进度:" + str(now_time_mins) + ':' + str(now_time_secs)
            else:
                self.current_time['text'] = "播放进度:" + ':' + str(self.now_time)
        else:
            continue

def main_Bottons(self):
    pygame.mixer.init()
    menbar = Menu(root)
    # 创建子菜单
    menuFile = Menu(menbar)
    menuAboutUs = Menu(menbar)
    # 将子菜单加入到主菜单
    menbar.add_cascade(label="文件(F)", menu=menuFile)
    menbar.add_cascade(label="关于(H)", menu=menuAboutUs)
    # 添加菜单项
    menuFile.add_command(label="打开文件夹", accelerator="ctrl-a", command=self.Music_Load)
    menuFile.add_command(label="清空列表", command=self.Clear_music)
    menuAboutUs.add_command(label='帮助', command=self.help_music)
    root["menu"] = menbar

    '''加载主菜单按键'''

    # 可变字符串组件
    self.pause_resume = tkinter.StringVar(self.master, value='播放')

    # 暂停/播放按键
    self.botton_Music_pause = ttk.Button(self.master, textvariable=self.pause_resume, command=self.Music_pause,
                                         padding='-4 -4 0 0')
    self.botton_Music_pause['image'] = self.play_photo
    self.botton_Music_pause.place(x=200, y=45, width=40, height=40)
    self.botton_Music_pause['state'] = self.botton_active

    # 上一首按键
    self.botton_Up_Music = ttk.Button(self.master, text='上一首', command=self.Up_Music, padding='-4 -4 10 0')
    self.botton_Up_Music['image'] = self.Up_photo
    self.botton_Up_Music.place(x=170, y=50, width=30, height=30)
    self.botton_Up_Music['state'] = self.botton_active

    # 下一首按键
    self.botton_Next_Music = ttk.Button(self.master, text='下一首', command=self.Next_Music, padding='-4 -4 10 0')
    self.botton_Next_Music['image'] = self.Next_photo
    self.botton_Next_Music.place(x=240, y=50, width=30, height=30)
    self.botton_Next_Music['state'] = self.botton_active

    # 添加单首按钮
    self.botton_Music_add = ttk.Button(self.master, text="添加", image=self.add_photo, command=self.Music_add,
                                       padding='0 -5 0 30')
    self.botton_Music_add.place(x=370, y=110, width=50, height=40)
    self.botton_Music_add['state'] = 'normal'

    # 删除按键
    self.botton_Music_delete = ttk.Button(self.master, text='删除', image=self.delete_photo,
                                          command=self.Music_delete, padding='0 -5 0 30')
    self.botton_Music_delete.place(x=430, y=110, width=50, height=40)
    self.botton_Music_delete['state'] = self.botton_active

    # 停止播放音乐
    self.botton_Stop_Music = ttk.Button(self.master, text='停止', command=self.Stop_Music, padding='-1 -2 0 0')
    self.botton_Stop_Music['image'] = self.stop_photo
    self.botton_Stop_Music.place(x=120, y=48, width=35, height=35)
    self.botton_Stop_Music['state'] = self.botton_active

    '''播放模式选择'''
    # 模式选择符
    mode = tkinter.StringVar(self.master)
    mode.set('模式')
    self.optionals = ttk.OptionMenu(self.master, mode, '', '顺序播放', '随机播放', '循环播放',
                                    command=self.mode_chose)
    self.optionals['image'] = self.optionals_order_photo
    self.optionals.place(x=280, y=38, width=55, height=55)
    self.optionals['state'] = 'normal'

    # 音量控制
    self.botton_control_voice = ttk.Scale(self.master, from_=0, to=100, orient=tkinter.HORIZONTAL,
                                          command=self.control_voice)
    self.botton_control_voice.set(self.vol)
    # pygame.mixer.music.set_volume(0.5)
    self.botton_control_voice.place(x=40, y=123, width=200)
    self.botton_control_voice['state'] = self.botton_active

    self.value_botton = ttk.Button(self.master, image=self.voice_play_photo, command=self.mult,
                                   padding='-4 -4 10 0')
    self.value_botton.place(x=5, y=115, width=30, height=30)

    # 播放器状态
    self.play_state = tkinter.StringVar(self.master, value='等待播放...')
    stateLabel = ttk.Label(self.master, textvariable=self.play_state, foreground='green', anchor='center',
                           relief=SUNKEN)
    # stateLabel.place(x=10, y=4, width=500, height=15)
    stateLabel.pack(side=TOP, fill=X)

    # 当前音乐
    self.musicName = tkinter.StringVar(self.master, value='')
    # labelName = tkinter.Label(self.master, textvariable=self.musicName, font=("微软雅黑", 12), fg='#008c8c')
    # labelName.place(x=10, y=500, width=400, height=30)

    # 进度条显示
    self.length_label = ttk.Label(self.master, text="总时长: --:--")
    self.length_label.place(y=90, width=140, height=20)

    self.current_time = ttk.Label(self.master, text="播放进度: --:--", relief=GROOVE)
    self.current_time.pack(side=BOTTOM, fill=X)

    # 音乐播放列表
    self.var = tkinter.StringVar()
    scrolly = Scrollbar(self.master)
    scrolly.pack(side=RIGHT, fill=Y)
    self.lb = tkinter.Listbox(self.master, listvariable=self.var, yscrollcommand=scrolly.set)
    self.lb.place(y=150, width=480, height=300)
    scrolly.config(command=self.lb.yview)

    # 快捷键绑定
    #root.bind('', lambda event: self.add_voice_value())
    #root.bind('', lambda event: self.del_voice_value())
    root.bind('', lambda event: self.Music_delete())
    root.bind('', lambda event: self.Music_delete())
    root.bind('', lambda event: self.Up_Music())
    root.bind('', lambda event: self.Next_Music())
    root.bind('', lambda event: self.Stop_Music())
    root.bind('', lambda event: self.Music_Load())
    root.bind('', lambda event: self.Close_windows())
    # root.bind('', lambda event: self.Music_play())  # 左键双击播放
    # root.mainloop()

def help_music(self):
    messagebox.showinfo('帮助', "我也不知道写了个什么玩意,反正能运行。")

def Music_Load(self):  # 加载音乐完成!
    self.filebox = filedialog.askdirectory()
    if self.filebox:
        musics = [self.filebox + "/" + music
                  for music in os.listdir(self.filebox) if music.endswith(('.mp3', '.m4a', '.wav'))]
        for each_music in musics:
            name = each_music.split('/')[-1]
            self.filename.append(name)
            self.filepath.append(each_music)
    if not self.filebox:
        return
    # var = tkinter.StringVar()
    self.var.set(self.filename)
    # self.lb = tkinter.Listbox(self.master, listvariable=var)
    # self.lb.place(y=150, width=500, height=300)

    self.botton_active = 'normal'
    self.botton_Music_delete['state'] = self.botton_active
    self.botton_Music_pause['state'] = self.botton_active
    self.botton_control_voice['state'] = self.botton_active

def Music_add(self):  # 单曲添加完成!
    music_path = filedialog.askopenfilename(filetypes=[('音乐', ('*.m4a', '*.wav', '*.mp3'))])
    if music_path:
        self.filebox.append(os.path.dirname(music_path))
        music_name = os.path.basename(music_path)
        self.filename.append(music_name)
        self.filepath.append(music_path)
        index = len(self.filename)
        self.lb.insert(index - 1, music_name)

        self.botton_active = 'normal'
        self.botton_Music_delete['state'] = self.botton_active
        self.botton_Music_pause['state'] = self.botton_active
        self.botton_control_voice['state'] = self.botton_active
    else:
        return

def Clear_music(self):  # 清空列表完成!
    if self.playing:
        self.Stop_Music()
    self.lb.delete(0, END)
    self.filepath = []
    self.filename = []
    self.filebox = []
    self.filepath.clear()
    self.filename.clear()
    self.musicName = None
    self.num = 0
    self.botton_Music_delete['state'] = 'disable'
    self.botton_Music_pause['state'] = 'disable'
    self.botton_Next_Music['state'] = 'disable'
    self.botton_Up_Music['state'] = 'disable'
    self.botton_Stop_Music['state'] = 'disable'

def mode_chose(self, event):  # 模式选择完成!
    if event is not None:
        self.default_mode = event
        if self.default_mode == '随机播放':
            self.mode_choose = self.default_mode
            self.optionals['image'] = self.optionals_rant_photo
        elif self.default_mode == '循环播放':
            self.mode_choose = self.default_mode
            self.optionals['image'] = self.optionals_circle_photo
        else:
            self.mode_choose = self.default_mode
            self.optionals['image'] = self.optionals_order_photo
    # print("模式选择:", self.mode_choose)

def Music_delete(self):  # 删除功能完成!
    if len(self.filename):
        music = self.lb.get('active')
        del_music = music.split('/')[-1]
        if self.musicName == del_music and self.playing:
            self.filename.remove(del_music)  # 需要删除的音乐正在播放
            self.Stop_Music()
            for i in self.filepath:
                if i.split('/')[-1] == del_music:
                    self.filepath.remove(i)
            self.lb.delete('active')

        elif self.playing:  # 音乐正在播放 删除其他的音乐
            self.filename.remove(del_music)
            for i in self.filepath:
                if i.split('/')[-1] == del_music:
                    self.filepath.remove(i)
            self.lb.delete('active')
        else:
            self.filename.remove(del_music)
            for i in self.filepath:
                if i.split('/')[-1] == del_music:
                    self.filepath.remove(i)
            self.lb.delete('active')
    else:
        self.botton_Music_delete['state'] = 'disable'
        self.botton_Music_pause['state'] = 'disable'

def Music_play(self):
    self.botton_Next_Music['state'] = self.botton_active
    self.botton_Up_Music['state'] = self.botton_active
    self.botton_Stop_Music['state'] = self.botton_active
    self.mode_choose = self.default_mode
    # print("播放模式:", self.mode_choose)

    if len(self.filepath) != 0:
        self.playing = True
        while self.playing:
            if not pygame.mixer.music.get_busy():
                nextMusic = self.filepath[self.num]
                # self.music_path = self.filepath[self.num]
                if self.get_mouse:  # 鼠标单击选择
                    nextMusic = self.lb.get('active')
                    temp_list = nextMusic
                    current_index = self.filename.index(temp_list)
                    self.num = current_index
                    nextMusic = self.filepath[current_index]
                    self.music_path = self.filepath[self.num]
                pygame.mixer.music.load(nextMusic)
                pygame.mixer.music.play()  # 单次播放
                self.get_mouse = False
                self.mode_choose = self.default_mode
                print(self.mode_choose)
                # self.playing = True
                nextMusic = nextMusic.split('/')[-1]
                self.musicName = nextMusic
                self.get_length()
                self.play_state.set('正在播放:\n{}'.format(self.musicName))
                # 播放模式选则
                if self.mode_choose == '随机播放':
                    self.num = random.randint(0, len(self.filepath) - 1)
                    if self.filename[self.num] == self.musicName:
                        self.num += 1
                elif self.mode_choose == '循环播放':
                    self.num = self.num
                elif self.mode_choose == '顺序播放':
                    if len(self.filepath) - 1 == self.num:
                        self.num = 0
                    else:
                        self.num += 1

def Music_pause(self):  # 暂停音乐完成!
    if self.filepath:
        if self.pause_resume.get() == '播放':
            self.play_state.set('正在播放:\n{}'.format(self.musicName))
            self.botton_Music_pause['image'] = self.pause_photo
            if not self.filebox:
                self.Music_Load()
            if not self.filebox:
                return
            self.playing = True
            t = threading.Thread(target=self.Music_play)
            t.start()
            self.pause_resume.set('暂停')
        elif self.pause_resume.get() == '暂停':
            pygame.mixer.music.pause()
            self.botton_Music_pause['image'] = self.play_photo
            self.playing = False
            self.play_state.set('暂停中:\n{}'.format(self.musicName))
            self.pause_resume.set('继续播放')
        elif self.pause_resume.get() == '继续播放' and self.playing is False:
            self.botton_Music_pause['image'] = self.pause_photo
            pygame.mixer.music.unpause()
            self.playing = True
            self.play_state.set('正在播放:\n{}'.format(self.musicName))
            self.pause_resume.set('暂停')

def Next_Music(self):
    if self.filebox:
        pygame.mixer.music.stop()
        if self.mode_choose == '顺序播放':
            if len(self.filepath) == self.num:
                self.num = 0

        elif self.mode_choose == '随机播放':  # 重复赋值了 在Music_Play里面
            self.num = random.randint(0, len(self.filepath) - 1)
            if self.filename[self.num] == self.musicName:
                self.num += 1

        elif self.mode_choose == '循环播放':
            if len(self.filepath) == self.num + 1:
                self.num = 0
            else:
                self.num += 1

        self.pause_resume.set('暂停')
        self.music_path = self.filepath[self.num]
        self.tag = True
        self.playing = False
        t = threading.Thread(target=self.Music_play)
        t.start()

def Up_Music(self):
    if self.filebox:
        pygame.mixer.music.stop()
        if self.mode_choose == '顺序播放':
            if self.num == 0:
                self.num = len(self.filepath) - 2
            elif self.num == len(self.filepath) - 1:
                self.num -= 2
            else:
                self.num -= 2

        elif self.mode_choose == '随机播放':
            self.num = random.randint(0, len(self.filepath))
            if self.filename[self.num] == self.musicName:
                self.num += 1

        elif self.mode_choose == '循环播放':
            if self.num == 0:
                self.num = len(self.filepath) - 1
            elif self.num == len(self.filepath) - 1:
                self.num -= 1
            else:
                self.num -= 1

        self.music_path = self.filepath[self.num]
        self.pause_resume.set('暂停')
        self.playing = False
        self.tag = True
        t = threading.Thread(target=self.Music_play)
        t.start()

def Stop_Music(self):  # 停止音乐完成!
    if self.filebox:
        self.playing = False
        pygame.mixer.music.unload()
        pygame.mixer.music.stop()
        self.pause_resume.set('播放')
        self.botton_Music_pause['image'] = self.play_photo
        self.play_state.set('等待播放...')
        self.get_mouse = True
        self.tag = True
        self.length_label['text'] = "总时长: --:--"

def Close_windows(self):  # 关闭后,后台依然在放 bug
    self.playing = False
    # self.Stop_Music()
    time.sleep(0.1)
    try:
        pygame.mixer.music.stop()
        pygame.mixer.quit()
    except Exception:
        print("关闭异常!")
    root.quit()
    root.destroy()
运行结果及报错内容

img

img

shell打印出来的错误信息是啥