简体   繁体   中英

Calling an external function that contains 'time.sleep()' within a Tkinter window

I am attempting to call an external function from the press of a button in a Tkinter GUI; the function 'insert's into a Text element. This works perfectly; as long as it is not followed closely by time.sleep(). If it isn't followed, the text updates correctly; if it is, the text does not update, though the function still seems to be running the loop, as it will happily print text to the console.

Here's my example script:

from Tkinter import *
from time import sleep

def test_function(gui_self):
    while True:
        print "Debug message"
        gui_self.main_.insert(END, "Test")


class GUI:
    def __init__(self, master):
        frame = Frame(master, width=300, height=500)
        frame.pack()
        self.main_ = Entry(frame, width=80, justify=CENTER)
        self.main_.pack()

        test_function(self)

root = Tk()
application = GUI(root)
root.mainloop()

This works well. However, changing test_function to the following seems to mess things up:

def test_function(gui_self):
    while True:
        print "Debug message"
        gui_self.main_.insert(END, "Test")
        sleep(5)

Any suggestions to fix whatever it is that I am doing wrong here? I'm sure it's just an issue that I, as a fairly basic level user, am not using the correct syntax for.

As a side note, the 'sleep' command also seems to freeze the program entirely, which I find rather annoying and unattractive. Is there a method to pause the loop for a variably set (eg, var = 1(second)) amount of time, other than 'pipe'ing threads, that would be efficient and more.. clean?

Thanks.

In general don't call time.sleep in a single threaded GUI otherwise you'll cause it to block as you've discovered.

The correct way to deal with sleeps is to use GUI events.

See this example in another Stack Overflow question which shows how to use the after method all TK root windows have.

I completely agree with Nick Craig-Wood's answer -- don't put the main thread of your gui to sleep. Generally, you want to call after which registers a function to be called after (approximately) X milliseconds. Here's an example that will call test_function every 5 seconds. Every time test_function is called, it will re-register itself to be called 5 seconds later.

def test_function(gui_self):
    print "Debug message"
    gui_self.main_.insert(END, "Test")
    gui_self.after(5000,test_function,gui_self)
    #the line below also should work.  As long as the item is a Tkinter widget
    #gui_self.main_.after(5000,test_function,gui_self) 

Also, completely unrelated, (but as a matter of style) -- is there a reason you're using main_ in GUI instead of just main ? Generally, trailing underscores are appended to aviod name-clashes with python keywords. As far as I know, main isn't a keyword.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM