Python:我的代码运行良好,但存在 GUI 冻结问题(使用 tkinter 和 sounddevice)

Python: my code works perfectly but there is a GUI freezing problem (using tkinter and sounddevice)

我有一个代码可以处理来自声音设备的音频数据。

我的代码通过 tkinter 构建 GUI,并在按下按钮时通过声音设备库处理音频数据。

当我 运行 代码时,它实际上工作得很好。但是,出现GUI冻结,无法点击按钮。

所以我尝试通过线程解决这个问题,但屡次失败

请检查我的代码并给我一些建议。

这是我的代码:

import sounddevice as sd
import numpy as np
import tkinter as tk
from tkinter import ttk
from threading import Thread


class Stream(Thread):
    def __init__(self):
        super().__init__()
        self.input_device_index = 2
        self.output_device_index = 4
        self.BLOCK_SHIFT = 128
        self.SAMPLING_RATE = 16000
        self.BLOCK_LEN = 512
        self.SOUND_DEVICE_LATENCY = 0.2
        self.start_streaming()

    def start_streaming(self):
        try:
            with sd.Stream(device=(self.input_device_index, self.output_device_index),
                       samplerate=self.SAMPLING_RATE, blocksize=self.BLOCK_SHIFT,
                       dtype=np.float32, latency=self.SOUND_DEVICE_LATENCY,
                       channels=1, callback=self.callback):
            input()

    except Exception as ex:
        print(str(type(ex).__name__ + ': ' + str(ex)))

    @staticmethod
    def callback(indata, outdata, frames, time, status):
        outdata[:] = indata


class App(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title("Please Help Me")
        self.geometry("400x300")
        self.resizable(0, 0)

        start_button = tk.Button(self, overrelief="solid", width=15,
                             command=lambda: Function.start_button_clicked(),
                             text="Start", repeatdelay=1000, repeatinterval=100)
        start_button.grid(column=0, row=5)


class Function:
    @staticmethod
    def start_button_clicked():
        stream = Stream()
        stream.start()


if __name__ == "__main__":
    app = App()
    app.mainloop()

您以错误的方式使用了 Thread 继承。您应该覆盖 class 中的 run() 方法。因此,将 start_streaming() 更改为 run() 并删除 __init__():

中的调用 start_streaming()
class Stream(Thread):
    def __init__(self):
        ...
        # should not call start_streaming() here
        #self.start_streaming()

    # rename start_streaming() to run()
    def run(self):
        ...