[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