Кнопка Tkinter- python не отвечает, когда в oop другой функции - PullRequest
0 голосов
/ 16 апреля 2020

У меня есть GUI для записи звука. Есть две кнопки, начать и остановить запись. Внутри функции для начала записи есть al oop, которую я не могу удалить. Когда кнопка начала записи нажата, кнопка остановки не реагирует (из-за l oop в начале, которую я не могу удалить по нескольким причинам). Я хотел бы знать, есть ли способ решить эту проблему и заставить обе кнопки реагировать, даже когда программа находится в l oop начала записи, что является бесконечным l oop. Я использую 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()

Как мне go решить эту проблему, что я должен добавить к приведенному выше коду, чтобы кнопки реагировали в любое время? Требуется ли многопоточность? Если да, как я могу ввести его для кнопок в приведенном выше коде? Любые предложения очень ценятся! Заранее спасибо!

Ответы [ 2 ]

2 голосов
/ 16 апреля 2020

Вы можете использовать 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()
0 голосов
/ 16 апреля 2020

Например, вы можете добавить update в while True, чтобы получить GUI «в живых». В приведенном ниже коде сначала нажмите OK, он входит в while True l oop, но с update, GUI реагирует, когда вы нажимаете KO:

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 и еще хуже в рекурсивных вызовах ... в этих случаях вам следует управлять этим при обратном вызове.

...