2017-11-07 5 views
0

시간 기록 프로그램을 쓰고 있습니다. 코드를 작성했지만 GUI를 작성하는 데 어려움이 있습니다. 입력을 받아서 계산을 위해 버튼 이벤트 처리 기능을 사용하여 외부 함수로 보내는 항목이 있습니다.내 라벨이 다른 기능의 변수를 업데이트하지 않는 이유는 무엇입니까? Tkinter

프로그램을 실행하면 시간을 업데이트하는 레이블이 표시되지 않습니다. 내 textvariables와 관련이 있는지 궁금해.

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

답변

0

코드에 몇 가지 문제가 있습니다. printv, timeLabel을 다시 정의하고 while 루프의 모든 단계에서 새로운 Tk() 개체를 만듭니다. 더 중요하게는 을 StringVar으로 정의하지만 즉시 문자열로 다시 정의하십시오. while 루프의 외부에을 한 번 정의한 다음 set() 메서드를 printv으로 사용해야합니다.


여기는 Tkinter의 아주 기본적인 타이머입니다. 무엇보다도 이 아니고 time.sleep 또는 while 루프를 사용해야합니다. mainloop 함수는 이미 while 루프이며, 대부분의 tkinter 객체는 시간 (밀리 초) 후에 이벤트를 호출 할 수있는 .after() 메소드를 가지고 있습니다.

전체 UI를 캡슐화하기위한 클래스를 만들었습니다. 모든 변수는 클래스 내에 저장되고 메소드에서 업데이트됩니다. 시간은 스크립트 자체 (현재 1 시간, 20 분, 10 초)로 설정되지만 명령 행이나 UI의 텍스트 필드에서 arg를 수락하도록 수정하기 쉽습니다.

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

while 루프에서 재정의하지 않을 경우 'timeLabel'을 어떻게 사용해야합니까? – wonderbreadhero

+0

'timeLabel'은 표시된 텍스트가 'printv' 객체에 연결된 Label 객체입니다. 'printv'를 변경하면'timeLabel'에 표시된 값이 바뀝니다. – James

+0

흥미 롭습니다. 나는'printv'에 set 메소드를 사용했지만,'timeLabel은 한 번만 업데이트됩니다. 마치 라벨이'printv'로 업데이트되지 않는 것과 같습니다. 위의 코드를 업데이트했습니다. – wonderbreadhero