Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
451 views
in Technique[技术] by (71.8m points)

python - How do you create a Tkinter GUI stop button to break an infinite loop?

So I have a Tkinter GUI with two simple options, a start and stop button. I have defined the GUI layout:

from Tkinter import *

def scanning():
    while True:
        print "hello"

root = Tk()
root.title("Title")
root.geometry("500x500")

app = Frame(root)
app.grid()

Here the Start button runs the infinite loop scanning, and the Stop button should break on press:

start = Button(app, text="Start Scan",command=scanning)
stop = Button(app, text="Stop",command="break")

start.grid()
stop.grid()

However, when I hit the Start button, it is always pushed down (assuming because of the infinite loop). But, I cannot click on the Stop button to break out of the while loop.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You cannot start a while True: loop in the same thread that the Tkinter event loop is operating in. Doing so will block Tkinter's loop and cause the program to freeze.

For a simple solution, you could use Tk.after to run a process in the background every second or so. Below is a script to demonstrate:

from Tkinter import *

running = True  # Global flag

def scanning():
    if running:  # Only do this if the Stop button has not been clicked
        print "hello"

    # After 1 second, call scanning again (create a recursive loop)
    root.after(1000, scanning)

def start():
    """Enable scanning by setting the global flag to True."""
    global running
    running = True

def stop():
    """Stop scanning by setting the global flag to False."""
    global running
    running = False

root = Tk()
root.title("Title")
root.geometry("500x500")

app = Frame(root)
app.grid()

start = Button(app, text="Start Scan", command=start)
stop = Button(app, text="Stop", command=stop)

start.grid()
stop.grid()

root.after(1000, scanning)  # After 1 second, call scanning
root.mainloop()

Of course, you may want to refactor this code into a class and have running be an attribute of it. Also, if your program becomes anything complex, it would be beneficial to look into Python's threading module so that your scanning function can be executed in a separate thread.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...