Tkinter只调用after_idle一次

use*_*510 4 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()
Run Code Online (Sandbox Code Playgroud)

Bry*_*ley 8

应用程序处于空闲状态时,您应该每隔几分钟调用一次,而不是一直调用该函数.例如,如果你想每秒检查10次,你会做这样的事情:

def checkForGroupUpdates(self):
    <do whatever you want>
    self.after(100, self.checkForGroupUpdates)
Run Code Online (Sandbox Code Playgroud)

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


Gab*_*les 7

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

这同样适用于该after_idle()功能.你必须在底部再次checkForGroupUpdates打电话after_idle().

下面是文档after,after_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)
Run Code Online (Sandbox Code Playgroud)

要使用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)
Run Code Online (Sandbox Code Playgroud)

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

使用的替代方案

        self.master.update_idletasks()
        self.master.after_idle(self.poll)
Run Code Online (Sandbox Code Playgroud)

是用来:

        #Method 3
        self.master.update_idletasks()
        self.master.after(0, self.poll)
Run Code Online (Sandbox Code Playgroud)

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

        #Method 4
        self.master.after(1, self.poll)
Run Code Online (Sandbox Code Playgroud)

还要注意,上面所有的例子,呼吁self.poll()__init__功能就是踢它全部关闭,并存储masterself.master需要简单地让里面poll,你可以调用afterafter_idle通过功能self.master.after_idle,例如.

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

问:上述每种方法的速度比较是多少?
A:

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

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