为什么我的标签不更新来自不同函数的变量? Tkinter

Why is my label not updating variable from different function? Tkinter

我正在写一个时钟程序。我已经构建了代码,但在围绕它创建 GUI 时遇到了问题。我有接受输入并将它们发送到外部函数的条目,并带有用于计算的按钮事件处理。

运行程序,我没有得到更新时间的标签。我想知道这是否与我的文本变量有关。

from tkinter import *
import time
import os


def show_entry_fields():
    hr= hrvar.get()
    mn = minvar.get()
    sc = secvar.get()
    counter = int(hr)*3600+int(mn)*60+ int(sc)

    mins = int(counter/60)
    hours = int(mins/60)

    hours = IntVar()
    mins = IntVar()
    secs = IntVar()

    while counter > 0:
       counter -= 1
       hours, sec = divmod(counter, 3600)
       mins, sec = divmod(sec, 60)
       printv = StringVar()




       printv = (" %d Hr:, %d Min: %d Sec" % (hours, mins, sec))
       win1 = Tk()
       timeLabel = Label(win1, textvariable= printv).grid(row=7)
       mins= int(counter/60)
       hours = int(mins/60)
       time.sleep(1)
       os.system('cls')
       return
   else:
       finishedLabel = Label(master, text="Time is Up").grid(row=7)
       return


  master = Tk()
  Label(master, text="Enter Hour(s)").grid(row=0)
  Label(master, text="Enter Mins(s)").grid(row=1)
  Label(master, text="Enter Second(s)").grid(row=2)

  hrvar = IntVar()
  minvar = IntVar()
  secvar = IntVar()
  e1 = Entry(master, textvariable = hrvar)
  e2 = Entry(master, textvariable = minvar)
  e3 = Entry(master, textvariable = secvar)

  e1.grid(row=0, column=1)
  e2.grid(row=1, column=1)
  e3.grid(row=2, column=1)

  Button(master, text='Quit', command=master.quit).grid(row=3, column=0, 
  sticky=W, pady=4)
  Button(master, text='Show', command=show_entry_fields).grid(row=3, 
  column=1, 
  sticky=W, pady=4)

  mainloop( )

更新代码。

class Timer:

   def __init__(self, master):
       #self.seconds = 0
       self.time = StringVar()
       self.hr = StringVar()
       self.mins = StringVar()
       self.secs = StringVar()

       self.hr_label = Label(master, text='Enter Hours').pack()
       self.entry_hr = Entry(master, textvariable = self.hr )
       self.entry_hr.pack()

       self.min_label = Label(master, text='Enter Minutes').pack()
       self.entry_min = Entry(master, textvariable = self.mins)
       self.entry_min.pack()



       self.time_label = Label(master, relief='flat', font=("Cambria", 20),
                              textvariable=self.time)
       self.set_time(hours= self.entry_hr.get(), minutes=self.entry_min.get(), seconds = 0)

       self.time.set('00:00:00')
       self.start_button = Button(master, text='Start')
       self.start_button.bind('<Button-1>', self.start_countdown)

       self.time_label.pack(padx=30, pady=10)
       self.start_button.pack(pady=(10,20))

   def set_time(self, hours, minutes, seconds):
       self.seconds = hours * 3600 + minutes * 60 + seconds
       self.time.set(self.format_time(self.seconds))

   def start_countdown(self, event):
       self.countdown()

   def countdown(self):
       if self.seconds <= 0:
           return
       self.seconds -= 1
       self.time.set(self.format_time(self.seconds))
       self.time_label.after(1000, self.countdown)

   def format_time(self, seconds):
       h = seconds // 3600
       m = (seconds - h*3600) // 60
       s = seconds - h*3600 - m*60
       return '{:0>2}:{:0>2}:{:0>2}'.format(h,m,s)

if __name__ == '__main__':
    root = Tk()
    timer = Timer(root)
    #timer.set_time(hours=0, minutes=20, seconds=0)
    root.mainloop()

您的代码有几个问题。您正在重新定义 printvtimeLabel,并在 while 循环的每一步创建一个新的 Tk() 对象。更重要的是,您将 printv 定义为 StringVar,但立即将其重新定义为字符串。您应该在 while 循环的 外部 定义它们中的每一个,然后使用 printv.

set() 方法

这是 Tkinter 中一个非常基本的计时器。首先,您应该 而不是 使用 time.sleepwhile 循环。 mainloop 函数已经是一个 while 循环,大多数 tkinter 对象都有一个 .after() 方法,允许您在 window 时间(以毫秒为单位)后调用事件。

请注意,我创建了一个 class 来封装我的整个 UI。所有变量都存储在 class 中并从其方法中更新。时间是在脚本本身中设置的(目前为 1 小时 20 分钟 10 秒),尽管很容易修改它以接受来自命令行或 UI.[=22= 中的文本字段的参数]

from tkinter import Tk, Label, StringVar
from tkinter.ttk import Button, Entry

class Timer:
    def __init__(self, master):
        self.seconds = 0
        self.time = StringVar()
        self.time_label = Label(master, relief='flat', font=("Cambria", 20),
                                textvariable=self.time)

        self.hr = StringVar()
        self.hr_label = Label(master, text='Hours:').grid(row=1, column=1, padx=5, pady=1)
        self.entry_hr = Entry(master, textvariable=self.hr, width=4)
        self.entry_hr.grid(row=1, column=2)

        self.mins = StringVar()
        self.min_label = Label(master, text='Minutes:').grid(row=2, column=1, padx=5, pady=1)
        self.entry_min = Entry(master, textvariable=self.mins, width=4)
        self.entry_min.grid(row=2, column=2)

        self.secs = StringVar()
        self.secs_label = Label(master, text='Seconds:').grid(row=3, column=1, padx=5, pady=1)
        self.entry_sec = Entry(master, textvariable=self.secs, width=4)
        self.entry_sec.grid(row=3, column=2)

        self.time.set('00:00:00')
        self.start_button = Button(master, text='Start')
        self.start_button.bind('<Button-1>', self.start_countdown)

        self.time_label.grid(row=0, columnspan=4, padx=30, pady=10)
        self.start_button.grid(row=4, columnspan=4, pady=(10,20))

    def set_time(self, hours, minutes, seconds):
        self.seconds = hours * 3600 + minutes * 60 + seconds
        self.time.set(self.format_time(self.seconds))

    def start_countdown(self, event):
        h = self.entry_hr.get()
        m = self.entry_min.get()
        s = self.entry_sec.get()
        h,m,s = map(lambda x: int(x) if x else 0, (h,m,s))
        self.set_time(h,m,s)
        self.countdown()

    def countdown(self):
        if self.seconds <= 0:
            return
        self.time.set(self.format_time(self.seconds))
        self.seconds -= 1
        self.time_label.after(1000, self.countdown)

    def format_time(self, seconds):
        h = seconds // 3600
        m = (seconds - h*3600) // 60
        s = seconds - h*3600 - m*60
        return '{:0>2}:{:0>2}:{:0>2}'.format(h,m,s)

if __name__ == '__main__':
    root = Tk()
    timer = Timer(root)
    root.mainloop()