简体   繁体   English

在Tkinter窗口中调用包含'time.sleep()'的外部函数

[英]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; 我试图通过按下Tkinter GUI中的按钮来调用外部函数; the function 'insert's into a Text element. 函数“插入”到Text元素中。 This works perfectly; 这很完美; as long as it is not followed closely by time.sleep(). 只要没有紧随其后的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: 但是,将test_function更改为以下内容似乎会使事情变得混乱:

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. 顺便提一句,“ sleep”命令似乎也完全冻结了程序,我觉得这很烦人并且没有吸引力。 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? 除了“管道”线程之外​​,是否有一种方法可以使循环暂停一段可变的时间(例如,var = 1(second)),这会更有效且更干净。

Thanks. 谢谢。

In general don't call time.sleep in a single threaded GUI otherwise you'll cause it to block as you've discovered. 通常,不要在单个线程的GUI中调用time.sleep ,否则您将发现它导致其阻塞。

The correct way to deal with sleeps is to use GUI events. 处理睡眠的正确方法是使用GUI事件。

See this example in another Stack Overflow question which shows how to use the after method all TK root windows have. 请参阅另一个堆栈溢出问题中的示例, 问题说明了如何使用所有TK根窗口具有的after方法。

I completely agree with Nick Craig-Wood's answer -- don't put the main thread of your gui to sleep. 我完全同意Nick Craig-Wood的回答-不要让gui的主线程进入睡眠状态。 Generally, you want to call after which registers a function to be called after (approximately) X milliseconds. 通常,您要在调用after注册(大约)X毫秒后要调用的函数。 Here's an example that will call test_function every 5 seconds. 这是一个示例,每5秒调用一次test_function Every time test_function is called, it will re-register itself to be called 5 seconds later. 每次调用test_function时,它将在5秒后重新注册为自身。

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 ? 另外,完全不相关(但仅作为样式问题)–是否有理由在GUI使用main_而不是仅使用main Generally, trailing underscores are appended to aviod name-clashes with python keywords. 通常,结尾的下划线会使用python关键字附加到aviod名称冲突中。 As far as I know, main isn't a keyword. 据我所知, main不是关键字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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