Tkinter只调用after_idle一次

时间:2013-08-28 22:09:40

标签: python user-interface tkinter

我是Tkinter的新手,所以如果这很容易,我会道歉,但我已经搜索了几个小时而且无法理解。我想要做的是在mainloop空闲之后,我总是想调用函数checkForGroupUpdates()。当我运行下面的代码时,它只运行一次。我不知道每次主循环空闲时它都会运行。我很感激帮助。

from Tkinter import *
import random

class Network(Frame):  
    """ Implements a stop watch frame widget. """                                                               
    def __init__(self, parent=None, **kw):      
        Frame.__init__(self, parent, kw)
        self.makeWidgets()    

    def makeWidgets(self):                       
        """ Make the time label. """
        self._canvas = Canvas(self, width=600, height=400)
        self._canvas.pack()

    def checkForGroupUpdates(self):
        print "checking"
        h=0
        this=10
        while this>.0001:
            this=random.random()
            print h
            h=h+1
        print "checked"


def main():
    root = Tk()
    nw = Network(root)
    nw.pack(side=TOP)

    root.after_idle(nw.checkForGroupUpdates)
    root.mainloop()


if __name__ == '__main__':
    main()

2 个答案:

答案 0 :(得分:8)

除了在应用程序空闲时始终调用该函数,您应该每隔一秒钟调用一次。例如,如果你想每秒检查10次,你会做这样的事情:

def checkForGroupUpdates(self):
    <do whatever you want>
    self.after(100, self.checkForGroupUpdates)

一旦你调用了那个函数,就会安排在100ms内再次调用它。这将持续到程序退出。如果程序变为“非空闲”(即:响应按钮单击时),此函数将暂停,因为tkinter是单线程的。一旦程序再次空闲,检查将继续。

答案 1 :(得分:5)

@ user1763510,请注意,在Bryan Oakley的回答中,他再次checkForGroupUpdates致电self.after。这是因为self.after仅执行单个调用,因此重复调用需要让它在第一次调用调用的函数内调用自身。这样,它就会不断地自我调用。

after_idle()功能也是如此。您必须在底部再次checkForGroupUpdates拨打after_idle()

以下是afterafter_idle等的文档。after说明中甚至还有一些示例,这一点很清楚。

文档:http://effbot.org/tkinterbook/widget.htm

上面的链接示例,在after说明:

#Method 1
class App:
    def __init__(self, master):
        self.master = master
        self.poll() # start polling

    def poll(self):
        ... do something ...
        self.master.after(100, self.poll)

要改为使用after_idle,它看起来像这样:

#Method 2
class App:
    def __init__(self, master):
        self.master = master
        self.poll() # start polling

    def poll(self):
        ... do something ...
        self.master.update_idletasks()
        self.master.after_idle(self.poll)

注意添加了self.master.update_idletasks()行。这将绘制GUI并处理按钮和按钮。否则,after_idle()将占用所有资源,而不是让{GUI 1}}中的GUI自动更新。

使用

的替代方法
mainloop()

是使用:

        self.master.update_idletasks()
        self.master.after_idle(self.poll)

使用 #Method 3 self.master.update_idletasks() self.master.after(0, self.poll) 是我的首选技术,因为它允许我轻松地将0更改为其他内容,如果我决定不需要经常运行self.poll。通过将延迟时间增加到至少1 ms,您根本不需要再调用self.master.after(0, self.poll)。所以,这也有效:

self.master.update_idletasks()

另请注意,对于上述所有示例,在 #Method 4 self.master.after(1, self.poll) 函数中调用self.poll()就可以解决这个问题,并且只需将__init__存储到master中就可以了在self.master内,您可以通过poll调用afterafter_idle函数。

问:这是否稳定/是否有效?
答:我使用上面的方法3运行了一个测试代码~21小时,并且它一直运行稳定,允许GUI可用而且全部。

问:上述每种方法的速度比较是什么?
答:

  • 方法1 :(我没有加速测试)
  • 方法2:~0.44 ms /迭代
  • 方法3:~0.44 ms /迭代
  • 方法4:~1.61 ms /迭代

问:哪个是我首选的方法?
答:方法3或4。