views:

87

answers:

2

I'm trying to make a simple program that continually displays and updates a label that displays the CPU usage, while having other unrelated things going on.

I've done enough research to know that threading is likely going to be involved. However, I'm having trouble applying what I've seen in simple examples of threading to what I'm trying to do.

What I currently have going:

import Tkinter
import psutil,time

from PIL import Image, ImageTk

class simpleapp_tk(Tkinter.Tk):
    def __init__(self,parent):
        Tkinter.Tk.__init__(self,parent)
        self.parent = parent
        self.initialize()

    def initialize(self):

        self.labelVariable = Tkinter.StringVar()
        self.label = Tkinter.Label(self,textvariable=self.labelVariable)
        self.label.pack()

        self.button = Tkinter.Button(self,text='button',command=self.A)
        self.button.pack()

    def A (self):
        G = str(round(psutil.cpu_percent(), 1)) + '%'
        print G

        self.labelVariable.set(G)

    def B (self):
        print "hello"


if __name__ == "__main__":
    app = simpleapp_tk(None)
    app.mainloop()

In the above code I'm basically trying to get command A continually running, while allowing command B to be done when the users presses the button.

+3  A: 

You should never attempt to alter a UI element from a thread that isn't the main thread.

What you probably want is after(delay_ms, callback, args). Some information can be over at http://www.pythonware.com/library/tkinter/introduction/x9507-alarm-handlers-and-other.htm.

As a sample, here's a quick script to show a clock (Note: I've never really used Tk).

from Tkinter import *
from time import strftime

class App(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.label_var = StringVar()
        self.label = Label(self, textvariable=self.label_var)
        self.label.pack()
        # Start the loop
        self.go()

    def go(self):
        self.label_var.set(strftime("%H:%M:%S"))
        # The callback is only called once, so call it every time
        self.after(1000, self.go)

app = App()
mainloop()
Justin Harper
A: 

You don't need threads for such a simple task. You can simply schedule your task to run every second or so, which can be done with the 'after' method;

First, add this method to your simpleapp_tk class:

def update(self):
    G = str(round(psutil.cpu_percent(), 1)) + '%'
    self.labelVariable.set(G)
    self.after(1000, self.update)

Then, in your initialize method add this call:

self.update()

This will cause the label to be updated to the current cpu value. The update method will then re-schedule itself to run again in one second.

Bryan Oakley