Tkinter-python 按钮在另一个函数的循环中没有响应

Tkinter-python button not responding when in a loop of another function

我有一个用于录制音频的 GUI。有两个按钮,开始和停止录制。 开始录制功能中有一个循环,我无法删除。当按下开始录制按钮时,停止按钮没有响应(由于开始循环,我出于某些原因无法删除)。我想知道是否有办法解决这个问题并让两个按钮响应,即使程序处于开始录制的循环中,这是一个无限的 loop.I' 使用 python2。代码如下所示,

class RecAUD:

    def __init__(self, chunk=4000, frmat=pyaudio.paInt16, channels=1, rate=44100, py=pyaudio.PyAudio()):

        # Start Tkinter and set Title
        self.main = tk.Tk()
        self.collections = []
        self.var = StringVar()
        self.var.set('READY')
        self.main.geometry('1200x500')
        self.main.title('Demo')
        self.CHUNK = chunk
        self.FORMAT = frmat
        self.CHANNELS = channels
        self.RATE = rate
        self.p = py
        self.st = 1
        print("----------------------record device list---------------------")
        info = self.p.get_host_api_info_by_index(0)
        numdevices = info.get('deviceCount')
        for i in range(0, numdevices):
                if (self.p.get_device_info_by_host_api_device_index(0, i).get('maxInputChannels')) > 0:
                    print("Input Device id ", i, " - ", self.p.get_device_info_by_host_api_device_index(0, i).get('name'))

        print("-------------------------------------------------------------")

        self.index = int(input())
        print("recording via index "+str(self.index))

        self.stream = self.p.open(format=self.FORMAT, channels=self.CHANNELS, rate=self.RATE, input=True,input_device_index = self.index, frames_per_buffer=self.CHUNK)
        self.buttons = tkinter.Frame(self.main, padx=1, pady=50)
        self.buttons.pack(fill=tk.BOTH)     
        photo = PhotoImage(file = r"stt.png")
        photoimage = photo.subsample(5, 5) 
        self.strt_rec = tkinter.Button(self.buttons, width=100, padx=8, pady=25, text='\n\n\n\nStart Recording', command=lambda: self.start_record(), bg='white', image = photoimage, compound = CENTER)
        self.strt_rec.grid(row=0, column=0, columnspan=2, padx=50, pady=5)

        self.stop_rec = tkinter.Button(self.buttons, width=100, padx=8, pady=25, text='\n\n\n\nStop Recording', command=lambda: self.stop_record(), bg='white', image = photoimage, compound = CENTER)
        self.stop_rec.grid(row=0, column=1, columnspan=2, padx=450, pady=5) 

        self.op_text = Label(self.main,textvariable = self.var,foreground="green",font = "Times 30 bold italic")
        self.op_text.place(x=350,y=100,anchor=NW)
        self.op_text.pack()
        tkinter.mainloop()

    def start_record(self):
        WAVE_OUTPUT_FILENAME = "recordedFile.wav"
        while True:
            data_frame = self.stream.read(self.CHUNK)
            data_int16_frame = list(struct.unpack(str(self.CHUNK) + 'h', data_frame))
            ...
            ...
    def stop_record(self):
        self.stream.stop_stream()
        self.stream.close()
        self.p.terminate()

guiAUD = RecAUD()

我该如何解决这个问题,我应该在上面的代码中添加什么来使按钮随时响应?是否需要多线程?如果是,我如何为上面代码中的按钮引入它?非常感谢任何建议!提前致谢!

例如,您可以在 while True 中添加一个 update 来 kke GUI "alive"。 在下面的代码中,先按 OK,它进入 while True 循环,但使用 update,当您按 KO 时,GUI 会做出反应:

import tkinter as tk

a = 0

def action():
    global a
    while True:
        if a == 0:
            b.configure(bg="red")
        else:
            b.configure(bg="blue")
        w.update()

def reaction():
    global a
    a = 1

w = tk.Tk()

b = tk.Button(w, text="OK", command=action)
c = tk.Button(w, text="K0", command=reaction)
b.pack()
c.pack()

w.mainloop()

危险在于多次调用 action,递归调用更糟……在这些情况下,您应该在启动回调中管理它。

您可以使用threading一个用于创建线程的模块

import threading

class cls():
     def __init__():
         self.thrun = True

     def start_record(self):
         WAVE_OUTPUT_FILENAME = "recordedFile.wav"
         while self.thrun:
             data_frame = self.stream.read(self.CHUNK)
             data_int16_frame = list(struct.unpack(str(self.CHUNK) + 'h', data_frame))


     def click(self):
         self.th = threading.Thread(target=start_record)

     def stop(self):
         self.thrun = False
         self.th.join()