Question

I am creating a text based game, and would like to have a counter of how many seconds it has been running, this is my first time using tkinter so I'm not totally sure I'm doing it all correctly. I am running into the following issue where upt_label['text'] and upt_table being undefined when I try to update it with my counter() function.

This is with python 3.3, what do I need to reference to be able to change that variable inside of counter()?

from tkinter import *
import time
from threading import Thread

global upt_label

class OutBox(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent, background="black")

        self.parent = parent

        self.initUI()

    def initUI(self):
        self.parent.title("Text Adventure!")
        self.pack(fill=BOTH, expand=1)
        tpp_label = Label(self, text="Text Adventure!", fg="white", background="black", anchor="center", font=("Arial", 18))
        tpp_label.pack()
        upt_label = Label(self, text = "Uptime: 0", fg="white", background="black", anchor="center", font=("Arial", 12))
        upt_label.pack()

def main():
    root = Tk()
    root.geometry("560x720")
    app = OutBox(root)
    root.mainloop()

def counter():
    uptime = 0
    while True:
        upt_label['text'] = 'Uptime: %s' % uptime
        time.sleep(1)
        uptime = uptime + 1

gui_thread = Thread(target = main, args = ())
gui_thread.start()

upt_thread = Thread(target = counter, args = ())
upt_thread.start()

No correct solution

OTHER TIPS

Part of the problem you have is that there is no guarantee that the gui thread will initialize before your counter thread runs. To compound the problem, you can't safely access tkinter widgets from any thread except the one that created them. So, even if you solved the start up sequence problem, you still have this other problem to solve.

The good news is, you do not need threads for this problem. In fact, threads makes this problem harder.

If you want to run something every second, use after to call a function, then have that function use after to schedule itself to run again in one second.

Here's a rough example:

   def counter():
        global uptime
        uptime += 1
        upt_label['text'] = 'Uptime: %s' % uptime
        root.after(1000, counter)

Notice how this function will update the label, then arrange for itself to be called again after one second. This may have a little inaccuracy since it's not guaranteed to run precisely one second later. A more accurate solution is to save the time that the program started, then get the current time and do some math. This will give you a more accurate representation over the course of a long running program.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top