Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

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

python - Tkinter only calls after_idle once

I am new to Tkinter, so I apologize if this is easy, but I have search for a couple of hours and can't figure it out. What I want to do is after the mainloop is idle, I always want to call the function checkForGroupUpdates(). When I run the code below, it only runs once. I can't figure out to have it run every time the mainloop is idle. I appreciate the help.

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()
See Question&Answers more detail:os

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

1 Answer

0 votes
by (71.8m points)

@user1763510, notice that in Bryan Oakley's answer, he has checkForGroupUpdates call self.after again. This is because self.after only does a single call, so getting repeated calls requires having it call itself within the function that gets called by the first call. This way, it keeps repeatedly calling itself.

The same goes for the after_idle() function. You have to have checkForGroupUpdates call after_idle() again at the bottom.

Here is the documentation for after, after_idle, etc. There is even a little example in the after description, which makes it all clear.

Documentation: http://effbot.org/tkinterbook/widget.htm

Example from link above, under the afterdescription:

#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)

To use after_idle instead, it would look like this:

#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)

Notice the addition of the self.master.update_idletasks() line. This draws the GUI and handles button presses and things. Otherwise, after_idle() will suck up all resources and not let the GUI self-update properly in the mainloop().

An alternative to using

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

is to use:

        #Method 3
        self.master.update_idletasks()
        self.master.after(0, self.poll)

Using self.master.after(0, self.poll) is my preferred technique, as it allows me to easily change the 0 to something else if I decide I don't need to run self.poll constantly. By increasing the delay time to at least 1 ms, you no longer need to call self.master.update_idletasks() at all. So, this works too:

        #Method 4
        self.master.after(1, self.poll)

Also notice that for all examples above, calling self.poll() in the __init__ function is what kicks it all off, and storing master into self.master is necessary simply so that inside poll you can call the after or after_idle function via self.master.after_idle, for example.

Q: Is this stable/does it work?
A: I ran a test code using Method 3 just above for ~21 hrs, and it ran stably the whole time, allowing the GUI to be usable and all.

Q: What is the speed comparison for each method above?
A:

  • Method 1: (I didn't speed test it)
  • Method 2: ~0.44 ms/iteration
  • Method 3: ~0.44 ms/iteration
  • Method 4: ~1.61 ms/iteration

Q: Which is my preferred method?
A: Method 3 or 4.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...