Обновление виджета метки python/tkinter?

Я работаю над созданием виджета ярлыка python/tkinter для обновления его содержимого. В предыдущем потоке сегодня я следил за инструкциями о том, как собрать виджеты. Однако во время выполнения виджет ярлыка НЕ ​​изменяет содержимое, а просто сохраняет исходное содержимое. Насколько я могу судить, decment_widget() никогда не вызывается вообще. Любые идеи?

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()

Ответы

Ответ 1

Вы хотите установить метку textvariable с помощью StringVar; когда StringVar изменяется (вы вызываете myStringVar.set("text here")), текст текста метки также обновляется. И да, я согласен, это странный способ сделать что-то.

Смотрите книгу Tkinter для получения дополнительной информации об этом:

Вы можете связать переменную Tkinter с меткой. Когда содержимое переменной изменяется, метка автоматически обновляется:

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

v.set("New Text!")

Ответ 2

Я думаю, что вы получаете ошибку "ссылка перед назначением", потому что Python считает, что remaining находится в локальной области.

В Python 3 вы можете сказать nonlocal remaining. Но в Python 2 я не считаю, что есть способ ссылаться на нелокальную, неглобальную область. Это сработало для меня:

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()

Ответ 3

    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()