首页 > 解决方案 > python tkinter GUI冻结并且音乐播放器按钮不会多次使用

问题描述

我怎样才能使播放按钮尽可能多地工作,同时又能够使用 GUI 的其余部分而不让它冻结。

我希望能够多次使用播放按钮,但它一直在说

TypeError:无法腌制 _tkinter.tkapp 对象

当我使用线程时,它会说运行时错误:

线程只能启动一次

from tkinter import *
from tkinter import filedialog
import os
import winsound
import threading
import time
import multiprocessing

audio_list = []

class Main(Frame):

    def __init__(self, master):
        Frame.__init__(self, master, bg="white")
        self.audio_dictionary=audio_list
        self.gui()
        self.refresh()
        Thread_1 = multiprocessing.Process(target=self.gui, args=(self,))
        Thread_1.start()

    def gui(self):
        self.Thread_2 = multiprocessing.Process(target=self.play, args=(self,))
        self.play_button= Button(text='Play', command=self.play)
        self.play_button.grid(column=0, row=1, sticky='W')

        stop_button= Button(text="Stop", command=self.stop)
        stop_button.grid(row=1, column=0, columnspan=2, sticky='E')

        self.display_songs = Listbox(bd=5, relief=GROOVE)
        self.display_songs.grid(row=0, column=0, columnspan=2)

        import_button = Button(text="Import", command=self.import_files)
        import_button.grid(row=1, column=2, sticky='E')

        self.status_window = Listbox(bd=5, relief=GROOVE)
        self.status_window.grid(row=0, column=2)


    def import_files(self):
        self.selected_songs=filedialog.askopenfilenames(filetypes = [("wav file", "*")], title='Select wav files')
        counter=0
        for y in self.selected_songs:
            x=os.path.basename(y)
            self.audio_dictionary.append((x,y))
            print(x)
            self.display_songs.insert(counter, x)
            counter+=1
        for p in self.audio_dictionary:
            print(p)

    def play(self):
        if self.Thread_2.is_alive() is True:
            selection = self.display_songs.curselection()

            for item in selection:
                song=self.display_songs.get(item)

            for c in self.audio_dictionary:
                s=c[0]
            if song==s:
               direct=c[1]
            else:
                pass

            print(direct)
            winsound.PlaySound(direct, winsound.SND_FILENAME)
        else:
            pass

    def refresh(self):
        window.update()
        window.after(100, self.refresh)

    def stop(self):
        print("Stopped Music")
        winsound.PlaySound(None, winsound.SND_FILENAME)


window = Tk()
app = Main(window)
window.mainloop()

标签: pythontkinterwinsound

解决方案


您应该避免使用线程。特别是不要从工作线程调用 Tkinter GUI 方法。但在本例中,您不需要任何线程,因为 winsound 函数已经支持为您异步播放声音:

winsound.PlaySound(filename, winsound.SND_FILENAME | winsound.SND_ASYNC)

如文档所述,如果您想停止当前播放的声音,则将 None 作为第一个参数传递。


推荐阅读