[Tutor] update a window with tkinter
Michael P. Reilly
arcege@speakeasy.net
Wed, 26 Dec 2001 18:06:53 -0500
On Wed, Dec 26, 2001 at 10:49:47PM +0100, dean wrote:
> hi guys,
>
> right, i just wanted to build a little bandwidth monitor to show the
> current data rates coming in and out of my machine and to update itself
> every few seconds.
>
> after writing the script in php, i spent an unsuccessful day trying to
> compile php-gtk.
>
> then i though it would be quicker to learn python.i was right. i wrote
> the script in an hour, but i haven't been able to get the gui working.
> here's the problem:
>
> i was using this loop (with the external function traffic_rate() which
> grabs the data from ifconfig.
>
> try:
> i = 1
> while 1:
> root.mainloop(3000)
> if i == 1:
> print string.rjust('In (Kb/s)' , 10), string.rjust('Out (Kb/s)', 10)
> rates = traffic_rate(3)
> inrate = rates[0]
> outrate = rates[1]
> inrate = float(inrate / 1024)
> outrate = float(outrate / 1024)
> inrate = fpformat.fix(inrate , 2)
> outrate = fpformat.fix(outrate , 2)
> print string.center(inrate , 10), string.center(outrate, 10)
> output = 'In: '+inrate+'Kb/s Out: '+outrate+'Kb/s'
> status.set("%s", output)
> i = i + 1
> if i == 10:
> i = 1
>
> except KeyboardInterrupt:
> quitme()
>
> i used the following code to build the gui (i lifted the class StatusBar
> straight from the tkinter tutorial at www.pythonware.com):
>
> root =Tk()
> frame = Frame(root)
> frame.bind("<Button-1>", quitme)
> frame.pack()
> status = StatusBar(root)
> status.bind("<Button-1>", quitme)
> status.pack(side=BOTTOM, fill=X)
> text = "Dean's bandwidth monitor"
> status.set("%s", text)
>
> now, as you probably saw, i used root.mainloop(3000) in my loop to get
> it to update every 3 seconds, but none of the bindings work anymore. i
> can't even close the window - i have to kill the app or ctrl-c the
> console. however, if i use root.mainloop() anywhere, the bindings work
> and i can close the app, but my loop doesn't run and the window never
> updates.
Depending on what system you are using, a lot of events could be handled
in 3000 milliseconds, maybe too many for you to be seeing. But that
seems doubtful.
It may be better to put this into a function and use the after method,
which tells Tkinter to run a function every so often. I'm not sure
what you have for the widget of the StatusBar, i.e. if the "set" method
works correctly. But try this:
def update_status(status_widget):
rates = traffic_rate(3)
inrate = rates[0]
outrate = rates[1]
inrate = float(inrate / 1024)
outrate = float(outrate / 1024)
inrate = fpformat.fix(inrate , 2)
outrate = fpformat.fix(outrate , 2)
print string.center(inrate , 10), string.center(outrate, 10)
output = 'In: '+inrate+'Kb/s Out: '+outrate+'Kb/s'
status_widget.set("%s", output)
root.after(3000, update_status, (status,))
root.mainloop()
It may be possible that traffic_rate takes too long to run. If that
is the case, then both bits of code won't get back to Tkinter to update
events, including to responding to bindings.
-Arcege