如何通过在Tkinter(Python)中设置正确的“停止”按钮来中断线程/进程?

2024-04-19 09:00:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我想要一些关于制作某种“停止”按钮的基本问题,在我的例子中,它可以终止一系列的蜂鸣音:

from tkinter import *
import winsound
from random import randint

class App(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()
        self.widgets()

    def widgets(self):
        self.beep = Button(self, text = "Beep", command = play_beep)
        self.beep.pack()
        self.stop = Button(self, text = "Stop", command = stop_beep)
        self.stop.pack()

go_on = True
def play_beep():
    count = 10
    while go_on == True and count != 0:
        winsound.Beep(randint(100, 2500), 200)
        count -= 1

def stop_beep():
    go_on = False

root = Tk()
app = App(root)
root.mainloop()

当我按下“哔”按钮时,它和所有的图形用户界面都会卡住,直到哔声结束。谁能告诉我怎么修理它吗?在


Tags: fromimportselfappgoondefcount
2条回答

我不使用TKinter,但我相信您的按钮按下不会创建一个单独的线程或进程。按钮卡住的原因是因为play_nu-beep循环阻塞了GUI执行循环。所以我们使用线程。线程与GUI同时执行,因此基本上可以同时执行两件事(监听GUI事件和播放哔哔声)。在

import threading

class App(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.is_playing = False
        self.pack()
        self.widgets()

    def widgets(self):
        self.beep = Button(self, text = "Beep", command = self.play_beep)
        self.beep.pack()
        self.stop = Button(self, text = "Stop", command = self.stop_beep)
        self.stop.pack()

    def play_beep(self):
        self.is_running = True
        self.beep_th = threading.Thread(target=self.run)
        self.beep_th.start()

    def run(self):
        count = 10
        while self.is_running == True and count != 0:
            winsound.Beep(randint(100, 2500), 200)
            count -= 1

    def stop_beep(self):
        try:
            self.is_running = False
            self.beep_th.join(0)
            self.beep_th = None
        except (AttributeError, RuntimeError): # beep thread could be None
            pass

    def closeEvent(self, event): # This is a pyside method look for a TKinter equivalent.
        """When you close the App clean up the thread and close the thread properly."""
        self.stop_beep()
        super().closeEvent(event)

首先,您的问题与线程或进程无关。Tkinter是单螺纹的。在

如果要在tkinter程序中定期运行某个函数,则必须给事件循环一个处理事件的机会。典型的解决方案是这样做:

def play_beep(count=10):
    if go_on and count != 0:
        winsound.Beep(randint(100, 2500), 200)
        root.after(1000, play_beep, count=1)

这将导致蜂鸣音每秒(1000毫秒)播放十次。在每次调用之间,事件循环将有机会处理其他事件。在

现在,如果您正在运行的代码需要很长时间,则必须在单独的线程或进程中运行该代码。我对winsound.Beep一无所知,所以我不知道这是否必要。在

其次,为了能够中断它,您需要使go_on全局化,否则您只需设置一个永远不会被使用的局部变量。在

^{pr2}$

相关问题 更多 >