使用tkinter使用GUI创建计时器

2024-06-02 04:48:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试用python创建一个计时器,并使用tkinter将其放到GUI应用程序中。现在我已经有了一个算法,可以根据用户的输入慢慢倒计时。虽然我已经这样做了,但GUI应用程序会冻结到0,然后显示完成时间。如果有人能让我知道为什么它不能每秒显示时间的变化,我将不胜感激。下面是我的代码

import tkinter as tk
import tkinter.font as tkFont
import time


def navbar(self,page):
    page = page
    timerBtn = tk.Button(self.master, text = 'Timer', command = lambda: timers(self,page))
    timerBtn.place(x=0,y=550,width = 333,height = 50)
    
    ClockBtn = tk.Button(self.master, text = 'Clock', command = lambda: clocks(self,page))
    ClockBtn.place(x=333,y=550, width = 333, height = 50)
    
    stopWatchBtn = tk.Button(self.master, text = 'Stop Watch', command = lambda: stopWatchs(self,page))
    stopWatchBtn.place(x=666,y=550,width = 333, height = 50)
    
    
def timers(self,page):
    if page != 'Timer':
        self.master.destroy()
        root = tk.Tk()
        app = timer(root)
    
def clocks(self,page):
    if page != 'Clock':
        self.master.destroy()
        root = tk.Tk()
        app = clock(root)
    
def stopWatchs(self,page):
    if page != 'StopWatch':
        self.master.destroy()
        root = tk.Tk()
        app = stopWatch(root)
    

class timer():
    def __init__(self, master):
        self.master = master
        self.master.title("Clock Clone")
        self.master.geometry("999x600")
        
        self.place()
        
    def place(self):
        self.hoursLabel = tk.Label(self.master, text = 'Hours')
        self.hoursLabel.place(x=220,y=200)
        
        self.hoursEntry = tk.Entry(self.master)
        self.hoursEntry.place(x=200,y= 200,width = 20)
        
        self.hoursUpArrow = tk.Button(self.master, text = "\N{UPWARDS BLACK ARROW}",command = lambda: self.change('hours', 'Up'))
        self.hoursUpArrow.place(x=201, y= 170)
        
        self.hoursDownArrow = tk.Button(self.master, text = "\N{DOWNWARDS BLACK ARROW}",command = lambda: self.change('hours', 'Down'))
        self.hoursDownArrow.place(x=201, y= 225)
        
        self.minsLabel = tk.Label(self.master, text = 'Minutes')
        self.minsLabel.place(x=520,y=200)
        
        self.minsEntry = tk.Entry(self.master)
        self.minsEntry.place(x=500,y= 200, width = 20)
        
        self.minsUpArrow = tk.Button(self.master, text = "\N{UPWARDS BLACK ARROW}",command = lambda: self.change('mins', 'Up'))
        self.minsUpArrow.place(x=501, y= 170)
        
        self.minsDownArrow = tk.Button(self.master, text = "\N{DOWNWARDS BLACK ARROW}",command = lambda: self.change('mins', 'Down'))
        self.minsDownArrow.place(x=501, y= 225)
        
        self.secondsLabel = tk.Label(self.master, text = 'Seconds')
        self.secondsLabel.place(x=820,y=200)
        
        self.secondsEntry = tk.Entry(self.master)
        self.secondsEntry.place(x=800,y= 200, width = 20)
        
        self.secondsUpArrow = tk.Button(self.master, text = "\N{UPWARDS BLACK ARROW}",command = lambda: self.change('sec', 'Up'))
        self.secondsUpArrow.place(x=801, y= 170)
        
        self.secondsDownArrow = tk.Button(self.master, text = "\N{DOWNWARDS BLACK ARROW}",command = lambda: self.change('sec', 'Down'))
        self.secondsDownArrow.place(x=801, y= 225)

        self.cancelButton = tk.Button(self.master, text = 'Cancel', command = self.cancel)
        self.cancelButton.place(x=150,y=400)
        
        self.startButton = tk.Button(self.master, text= 'Start', command = self.start)
        self.startButton.place(x=750,y=400)

        navbar(self,'Timer')        
      
    def change(self,time, change):
        changeable = 0
        if time == 'hours':
            changeable = self.hoursEntry.get()
        elif time == 'mins':
            changeable = self.minsEntry.get()
        elif time == 'sec':
            changeable = self.secondsEntry.get()
         
        if changeable == '':
            changeable = 0
        else:
            changeable = int(changeable)
        
        if time == 'hours':
            if change == 'Up':
                changeable += 1
            else:
                if changeable > 0:
                    changeable -= 1
            self.hoursEntry.delete(0,tk.END)
            self.hoursEntry.insert(0,str(changeable))
        elif time == 'mins':
            if change == 'Up' and changeable < 60:
                changeable += 1
            else:
                if changeable > 0:
                    changeable -= 1
            self.minsEntry.delete(0,tk.END)
            self.minsEntry.insert(0,str(changeable))
        elif time == 'sec':
            if change == 'Up' and changeable < 60:
                changeable += 1
            else:
                if changeable > 0:
                    changeable -= 1
            self.secondsEntry.delete(0,tk.END)
            self.secondsEntry.insert(0,str(changeable))
    def cancel(self):
        self.place()
        self.TimeLabel.place_forget()
    
    def start(self):
        self.hours = self.hoursEntry.get()
        self.mins = self.minsEntry.get()
        self.seconds = self.secondsEntry.get()
        
        if self.hours == '':
            self.hours = '00'
        if self.mins == '':
            self.mins = '00'
        if self.seconds == '':
            self.seconds = '00'
            
        self.hours = int(self.hours)
        self.mins = int(self.mins)
        self.seconds = int(self.seconds)
        
        
        self.hoursLabel.place_forget()
        self.hoursEntry.place_forget()
        self.hoursUpArrow.place_forget()
        self.hoursDownArrow.place_forget()
        self.minsLabel.place_forget()
        self.minsEntry.place_forget()
        self.minsUpArrow.place_forget()
        self.minsDownArrow.place_forget()
        self.secondsLabel.place_forget()
        self.secondsEntry.place_forget()
        self.secondsUpArrow.place_forget()
        self.secondsDownArrow.place_forget()
        
        fontStyle = tkFont.Font(family="Lucida Grande", size=50)
        Time = str(self.hours) + ':' + str(self.mins) + ':' + str(self.seconds)
        
        self.TimeLabel = tk.Label(self.master, text = Time, font = fontStyle)
        self.TimeLabel.place(x=380, y= 200)
        self.on = True
        self.timer(Time)
    def timer(self,Time):
        time.sleep(1)
        self.seconds -= 1
        if self.seconds <= 0:
            if self.mins > 0:
                self.seconds = 60
                self.mins -= 1
            else:
                if self.hours >= 1:
                    self.mins = 59
                    self.seconds = 60
                    self.hours -= 1
                else:
                    self.on = False
                  
        Time = str(self.hours) + ':' + str(self.mins) + ':' + str(self.seconds)
        self.TimeLabel.config(text = Time)
        
        if self.on == True:
            self.timer(Time)
            
class clock():
    def __init__(self,master):
        self.master = master
        self.master.title("Clock Clone")
        self.master.geometry("999x600")



        navbar(self,'Clock')     
    
class stopWatch():
    def __init__(self,master):
        self.master = master
        self.master.title("Clock Clone")
        self.master.geometry("999x600")



        navbar(self,'StopWatch')     


root = tk.Tk()
app = timer(root)
root.mainloop()

Tags: textselfmasterifdefpageplacebutton
1条回答
网友
1楼 · 发布于 2024-06-02 04:48:44

下面是如何使用我在评论中提到的^{}小部件方法,让GUI应用程序的Timer类部分正常工作,而不会冻结注意:我还重新格式化了大量代码,使其更具可读性,并更改了类名的拼写,以符合PEP 8 - Style Guide for Python Code准则和(相当重要的)naming conventions。我强烈建议你自己阅读并开始关注它们

使其工作的代码更改主要是在Timerstart()方法中,现在没有人调用我添加的名为countdown()的新方法,它取代了您调用的timer()。我还更改了cancel()方法以使其工作

import tkinter as tk
import tkinter.font as tkFont
import time


def navbar(self, page):
    timerBtn = tk.Button(self.master, text='Timer',
                         command=lambda: timers(self, page))
    timerBtn.place(x=0, y=550, width=333, height=50)

    ClockBtn = tk.Button(self.master, text='Clock',
                         command=lambda: clocks(self, page))
    ClockBtn.place(x=333, y=550, width=333, height=50)

    stopWatchBtn = tk.Button(self.master, text='Stop Watch',
                             command=lambda: stopWatchs(self, page))
    stopWatchBtn.place(x=666, y=550, width=333, height=50)

def timers(self, page):
    if page != 'Timer':
        self.master.destroy()
        root = tk.Tk()
        app = Timer(root)

def clocks(self, page):
    if page != 'Clock':
        self.master.destroy()
        root = tk.Tk()
        app = Clock(root)

def stopWatchs(self, page):
    if page != 'StopWatch':
        self.master.destroy()
        root = tk.Tk()
        app = StopWatch(root)


class Timer:
    def __init__(self, master):
        self.master = master
        self.master.title("Clock Clone")
        self.master.geometry("999x600")
        self.place()

    def place(self):
        self.hoursLabel = tk.Label(self.master, text='Hours')
        self.hoursLabel.place(x=220,y=200)

        self.hoursEntry = tk.Entry(self.master)
        self.hoursEntry.place(x=200, y=200, width=20)

        self.hoursUpArrow = tk.Button(self.master, text="\N{UPWARDS BLACK ARROW}",
                                      command=lambda: self.change('hours', 'Up'))
        self.hoursUpArrow.place(x=201, y= 170)

        self.hoursDownArrow = tk.Button(self.master, text="\N{DOWNWARDS BLACK ARROW}",
                                      command=lambda: self.change('hours', 'Down'))
        self.hoursDownArrow.place(x=201, y= 225)

        self.minsLabel = tk.Label(self.master, text='Minutes')
        self.minsLabel.place(x=520,y=200)

        self.minsEntry = tk.Entry(self.master)
        self.minsEntry.place(x=500,y= 200, width=20)

        self.minsUpArrow = tk.Button(self.master, text="\N{UPWARDS BLACK ARROW}",
                                     command=lambda: self.change('mins', 'Up'))
        self.minsUpArrow.place(x=501, y=170)

        self.minsDownArrow = tk.Button(self.master, text="\N{DOWNWARDS BLACK ARROW}",
                                       command=lambda: self.change('mins', 'Down'))
        self.minsDownArrow.place(x=501, y= 225)

        self.secondsLabel = tk.Label(self.master, text='Seconds')
        self.secondsLabel.place(x=820,y=200)

        self.secondsEntry = tk.Entry(self.master)
        self.secondsEntry.place(x=800,y= 200, width=20)

        self.secondsUpArrow = tk.Button(self.master, text="\N{UPWARDS BLACK ARROW}",
                                        command=lambda: self.change('sec', 'Up'))
        self.secondsUpArrow.place(x=801, y= 170)

        self.secondsDownArrow = tk.Button(self.master, text="\N{DOWNWARDS BLACK ARROW}",
                                          command=lambda: self.change('sec', 'Down'))
        self.secondsDownArrow.place(x=801, y=225)

        self.cancelButton = tk.Button(self.master, text='Cancel', command=self.cancel)
        self.cancelButton.place(x=150,y=400)

        self.startButton = tk.Button(self.master, text= 'Start', command=self.start)
        self.startButton.place(x=750,y=400)
        navbar(self, 'Timer')

    def change(self,time, change):
        changeable = 0
        if time == 'hours':
            changeable = self.hoursEntry.get()
        elif time == 'mins':
            changeable = self.minsEntry.get()
        elif time == 'sec':
            changeable = self.secondsEntry.get()

        if changeable == '':
            changeable = 0
        else:
            changeable = int(changeable)

        if time == 'hours':
            if change == 'Up':
                changeable += 1
            else:
                if changeable > 0:
                    changeable -= 1
            self.hoursEntry.delete(0,tk.END)
            self.hoursEntry.insert(0,str(changeable))
        elif time == 'mins':
            if change == 'Up' and changeable < 60:
                changeable += 1
            else:
                if changeable > 0:
                    changeable -= 1
            self.minsEntry.delete(0,tk.END)
            self.minsEntry.insert(0,str(changeable))
        elif time == 'sec':
            if change == 'Up' and changeable < 60:
                changeable += 1
            else:
                if changeable > 0:
                    changeable -= 1
            self.secondsEntry.delete(0,tk.END)
            self.secondsEntry.insert(0,str(changeable))

    def cancel(self):
        self.on = False
        self.TimeLabel.place_forget()
        self.place()

    def start(self):
        self.hours = self.hoursEntry.get()
        self.mins = self.minsEntry.get()
        self.seconds = self.secondsEntry.get()

        if self.hours == '':
            self.hours = '00'
        if self.mins == '':
            self.mins = '00'
        if self.seconds == '':
            self.seconds = '00'

        self.hours = int(self.hours)
        self.mins = int(self.mins)
        self.seconds = int(self.seconds)

        self.hoursLabel.place_forget()
        self.hoursEntry.place_forget()
        self.hoursUpArrow.place_forget()
        self.hoursDownArrow.place_forget()
        self.minsLabel.place_forget()
        self.minsEntry.place_forget()
        self.minsUpArrow.place_forget()
        self.minsDownArrow.place_forget()
        self.secondsLabel.place_forget()
        self.secondsEntry.place_forget()
        self.secondsUpArrow.place_forget()
        self.secondsDownArrow.place_forget()

        fontStyle = tkFont.Font(family="Lucida Grande", size=50)
        time_string = f'{self.hours:2d}:{self.mins:02d}:{self.seconds:02d}'

        self.TimeLabel = tk.Label(self.master, text=time_string, font=fontStyle)
        self.TimeLabel.place(x=380, y=200)
        self.on = True
        self.master.after(1000, self.countdown)  # Start countdown in 1 second.

    def countdown(self):
        self.seconds -= 1
        if self.seconds <= 0:
            if self.mins > 0:
                self.seconds = 60
                self.mins -= 1
            else:
                if self.hours >= 1:
                    self.mins = 59
                    self.seconds = 60
                    self.hours -= 1
                else:
                    self.on = False

        time_string = f'{self.hours:2d}:{self.mins:02d}:{self.seconds:02d}'
        self.TimeLabel.config(text=time_string)

        if self.on:  # Not finished?
            self.master.after(1000, self.countdown)  # Call again in 1 second.


class Clock:
    def __init__(self,master):
        self.master = master
        self.master.title("Clock Clone")
        self.master.geometry("999x600")
        navbar(self, 'Clock')


class StopWatch:
    def __init__(self,master):
        self.master = master
        self.master.title("Clock Clone")
        self.master.geometry("999x600")
        navbar(self,'StopWatch')


root = tk.Tk()
app = Timer(root)
root.mainloop()

下面是它运行的屏幕截图:

screenshot of running app

相关问题 更多 >