28

I'm working on getting a python/tkinter label widget to update its contents. Per an earlier thread today, I followed instructions on how to put together the widgets. At runtime, however, the label widget does NOT change contents, but simply retains its original content. As far as I can tell, decrement_widget() is never called at all. Any ideas?

def snooze (secs):
  """
  Snoozes for the given number of seconds. During the snooze, a progress
  dialog is launched notifying the 
  """

  root = Tkinter.Tk()
  prompt = 'hello'
  label1 = Tkinter.Label(root, text=prompt, width=len(prompt))
  label1.pack()

  remaining = secs

  def decrement_label ():
    text = "Snoozing %d sec(s)" % remaining
    remaining -= 1
    label1.config(text=text, width=100)
    label1.update_idletasks()

  for i in range(1, secs + 1):
    root.after(i * 1000, decrement_label )

  root.after((i+1) * 1000, lambda : root.destroy())
  root.mainloop()
user229044
  • 232,980
  • 40
  • 330
  • 338
Stephen Gross
  • 5,274
  • 12
  • 41
  • 59

5 Answers5

46

You'll want to set the label's textvariable with a StringVar; when the StringVar changes (by you calling myStringVar.set("text here")), then the label's text also gets updated. And yes, I agree, this is a strange way to do things.

See the Tkinter Book for a little more information on this:

You can associate a Tkinter variable with a label. When the contents of the variable changes, the label is automatically updated:

v = StringVar()
Label(master, textvariable=v).pack()

v.set("New Text!")
Community
  • 1
  • 1
Mark Rushakoff
  • 249,864
  • 45
  • 407
  • 398
  • Per your recommendation, I changed the decrement_label function to 'text=...; remaining -=1; sv = Tkinter.StringVar(); sv.Set(text); label1.conf(text=sv, width=100); label1.update_idletasks()'. However, this has not had any effect on runtime behavior. The decrement_label function does NOT appear to be called at all! – Stephen Gross Dec 16 '09 at 21:59
  • I also figured out that the 'remaining -= 1' statement appears to be causing the problem. Python silently fails somehow when it encounters that statement. Is there something wrong with it? – Stephen Gross Dec 16 '09 at 22:23
  • You have to set the `StringVar` when you create the `Label`, and then modify that same instance of the `StringVar`. You shouldn't need to repeatedly call `label1.conf`. Post your fully updated code. – Mark Rushakoff Dec 16 '09 at 22:35
  • 9
    Note: using StringVar isn't strictly required. You can simply update the label widget directly with `configure`: `l=Label(...); ...; l.configure(text="new text")` which has the benefit of one less object to manage. – Bryan Oakley Apr 15 '16 at 15:30
  • effbot.org is taking a break. Does anyone know where a mirror of the Tkinter book might be hosted? – icedwater Oct 05 '21 at 10:54
9

I think you're getting a "referenced before assignment" error because Python thinks remaining is in the local scope.

In Python 3, you can say nonlocal remaining. But in Python 2, I don't believe there's a way to refer to a non-local, non-global scope. This worked for me:

remaining = 0

def snooze (secs):
  """
  Snoozes for the given number of seconds. During the snooze, a progress
  dialog is launched notifying the 
  """

  global remaining
  root = Tkinter.Tk()
  prompt = 'hello'
  label1 = Tkinter.Label(root, text=prompt, width=len(prompt))
  label1.pack()

  remaining = secs

  def decrement_label ():
    global remaining
    text = "Snoozing %d sec(s)" % remaining
    remaining -= 1
    label1.config(text=text, width=100)
    label1.update_idletasks()

  for i in range(1, secs + 1):
    root.after(i * 1000, decrement_label )

  root.after((i+1) * 1000, lambda : root.destroy())
  root.mainloop()
Fred Larson
  • 60,987
  • 18
  • 112
  • 174
1
    import tkinter
    from tkinter import *

    # just init some vars
    remaining = 0                
    secs = 0
    root = tkinter.Tk()
    prompt = StringVar()

    def snooze (secs):
      """
      Snoozes for the given number of seconds. During the snooze, a progress
      dialog is launched notifying the 
      """
      def decrement_label ():
        global remaining, prompt
        remaining -= 1
        prompt.set('Snoozing %d sec(s)' % remaining)
        label1.update_idletasks()
        if not remaining:
          print("end ... ")
          root.destroy()

      global remaining
      prompt.set("hello")
      label1 = tkinter.Label(root, textvariable=prompt, width=30)
      label1.pack()

      remaining = secs
      for i in range(1, secs + 1):
        root.after(i * 1000, decrement_label )

    snooze(10)
    root.mainloop()
bertil
  • 59
  • 1
  • 6
1

To update text in a label you can try the following:

from tkinter import *

root = Tk()
root.title("Title")
root.geometry('300x300')


def clear_text(self):
    txtE.delete(0, 'end')


def new_label(event=None):
    Entree = txtE.get()
    lbl1['text'] = Entree.title()
    clear_text(txtE)


lbl1 = Label(root, text='Hello There')
lbl1.pack()
txtE = Entry(root)
txtE.focus()
txtE.pack()

Button(root, text='Enter', command=new_label).pack()
Button(root, text='Quit', command=root.destroy).pack(side=BOTTOM)
root.bind('<Return>', new_label)
root.mainloop()
Michael Mulvey
  • 131
  • 1
  • 9
0

I think you have to call snooze(secs) function

After that if your code again not works try this

Set a variable

Variable = StringVar()

In the label widget you can set "textvariable" argument to the above mentioned "Variable".

Eg: label1 = Label(root,textvariable = Variable).pack()

And you can update by setting a new value to "Variable"

Eg:Variable.set("hi")

Hope you got it !!!