TKinter - 如何使用停止按钮停止循环?

Mat*_*era 5 python tkinter

我有这个程序每秒都会发出哔哔声,直到它停止.问题是,在我按下"开始"并开始发出哔声后,我无法点击"停止"按钮,因为窗口冻结了.欢迎任何帮助.

#!/usr/bin/python
import Tkinter, tkMessageBox, time, winsound, msvcrt

running = True

Freq = 2500
Dur = 150

top = Tkinter.Tk()
top.title('MapAwareness')
top.geometry('200x100') # Size 200, 200

def start():
    sec = 0
    while running:
        if sec % 1 == 0:
            winsound.Beep(Freq, Dur)

        time.sleep(1)
        sec += 1

def stop():
    running = False

startButton = Tkinter.Button(top, height=2, width=20, text ="Start", command = start)
stopButton = Tkinter.Button(top, height=2, width=20, text ="Stop", command = stop)

startButton.pack()
stopButton.pack()

top.mainloop()
Run Code Online (Sandbox Code Playgroud)

mar*_*eau 6

你的代码有几个问题.首先,你不应该time.sleep()在Tkinter程序中使用,因为它会干扰mainloop().相反,通常使用通用窗口小部件方法.after()来调度在指定延迟之后运行的函数.

其次,你没有正确使用全局变量.当您为函数中的命名变量赋值时,它将创建一个局部变量,除非该名称先前已声明过global.因此,例如,您的stop()函数正在创建一个名为的局部变量,running并将其值设置为0, 而不是更改具有相同名称的全局变量的值.

以前的规则不适用于仅引用(读取)变量的当前值.这就是为什么没有声明FreqDur全局变量的原因start().

另一个问题是sec % 1 == 0你的start()功能.任何价值% 1都是0.检查奇数/均匀度sec % 2.

这是一个工作版本,也已经重新格式化,以更紧密地遵循PEP 8 - Python代码风格指南.

import Tkinter
import tkMessageBox
import time
import winsound

FREQ = 2500
DUR = 150

after_id = None
secs = 0

def beeper():
    global after_id
    global secs
    secs += 1
    if secs % 2 == 0:  # every other second
        winsound.Beep(FREQ, DUR)
    after_id = top.after(1000, beeper)  # check again in 1 second

def start():
    global secs
    secs = 0
    beeper()  # start repeated checking

def stop():
    global after_id
    if after_id:
        top.after_cancel(after_id)
        after_id = None

top = Tkinter.Tk()
top.title('MapAwareness')
top.geometry('200x100')

startButton = Tkinter.Button(top, height=2, width=20, text="Start",
                             command=start)
stopButton = Tkinter.Button(top, height=2, width=20, text="Stop",
                            command=stop)
startButton.pack()
stopButton.pack()
top.mainloop()
Run Code Online (Sandbox Code Playgroud)