【问题标题】:Python Tkinter Stopwatch ErrorPython Tkinter 秒表错误
【发布时间】:2015-07-23 11:01:43
【问题描述】:

我用 python 和 tkinter 做了一个双倒数计时器,但是如果 tkinter 窗口不在前台并且它不能同时运行,它似乎无法运行。这是我的代码:

import tkinter as tk
import tkinter.ttk as ttk
import time
class app:

 def __init__(self):
   self = 0

 def mainGUIArea():
    def count_down_1():
        for i in range(79, -1, -1):
            timeCount = "{:02d}:{:02d}".format(*divmod(i, 60))
            time_str.set(timeCount)
            root.update()
            time.sleep(1)

    def count_down_2():
        for j in range(10, -1, -1):
            timeCount = "{:02d}:{:02d}".format(*divmod(j, 60))
            time_str1.set(timeCount)
            root.update()
            time.sleep(1)

    #Main Window
    root = tk.Tk()
    root.title("Super Timer V1.0")
    root.minsize(300,300)
    root.geometry("500x300")

    #Timer1
    time_str = tk.StringVar()
    label_font = ('Courier New', 40)
    tk.Label(root, textvariable = time_str, font = label_font, bg = 'white', fg = 'blue', relief = 'raised', bd=3).pack(fill='x', padx=5, pady=5)
    tk.Button(root, text=' Start Timer! ',bg='lightgreen',fg='black', command=count_down_1).pack()
    tk.Button(root, text='Stop and Exit',bg='red',fg='white', command=root.destroy).pack()

    #Timer2
    time_str1 = tk.StringVar()
    label_font = ('Courier New', 40)
    tk.Label(root, textvariable = time_str1, font = label_font, bg = 'white', fg='blue', relief='raised', bd=3).pack(fill='x', padx=5, pady=5)
    tk.Button(root, text=' Start Timer! ',bg='lightblue',fg='black', command=count_down_2).pack()
    tk.Button(root, text='Stop and Exit',bg='red',fg='white', command=root.destroy).pack()


def main():
  app.mainGUIArea()

main()

你有什么建议吗?谢谢你:)

【问题讨论】:

  • 使用root.after方法。

标签: python tkinter


【解决方案1】:

time.sleep 的调用至少是问题的一部分。当您调用 sleep 时,它实际上就是这样做的——它使应用程序进入睡眠状态。无法处理任何事件并且 GUI 冻结。这是做倒数计时器的错误方法。

另一个问题是循环内对update 的调用以及对time.sleep 的调用。此调用将处理事件,这意味着当其中一个循环正在运行并且您单击一个按钮时,您最终可能会调用另一个函数,从而将两个循环交错。

定期做某事的正确方法是使用after 重复调用一个函数。一般模式是这样的:

def update_display(self):
    <do whatever code you want to update the display>
    root.after(1000, self.update_display)

您可以让任意数量的这些并行运行(显然达到实际限制),并且您的 GUI 将在更新之间完全响应。

这是一个简单的例子:

class Countdown(tk.Label):
    def __init__(self, parent):
        tk.Label.__init__(self, parent, width=5, text="00:00")
        self.value = 0
        self._job_id = None

    def tick(self):
        self.value -= 1
        text = "{:02d}:{:02d}".format(*divmod(self.value, 60))
        self.configure(text=text)
        if self.value > 0:
            self._job_id = self.after(1000, self.tick)

    def start(self, starting_value=60):
        if self._job_id is not None: return

        self.value = starting_value
        self.stop_requested = False
        self.after(1000, self.tick)

    def stop(self):
        self.after_cancel(self._job_id)
        self._job_id = None

【讨论】:

    【解决方案2】:

    这是我制作的一个简单的 tkinter(gui) 秒表,效果很好。看看吧

    __author__ = 'Surya'
    from tkinter import *
    import time
    class StopWatch(Frame):
        def __init__(self, parent = None, ** kw):
            Frame.__init__(self, parent, kw)
            self._timeelapsed = 0.0
            self._start = 0.0
            self._run = 0
            self.timestr = StringVar()
            self.makeWidgets()
        def makeWidgets(self):
            l = Label(self, textvariable=self.timestr)
            self._setTime(self._timeelapsed)
            l.pack(fill=X, expand=NO, pady=2, padx=2)
    
        def _update(self):
            self._timeelapsed = time.time() - self._start
            self._setTime(self._timeelapsed)
            self._timer = self.after(50, self._update)
    
        def _setTime(self, elap):
            minutes = int(elap/60)
            seconds = int(elap - minutes*60.0)
            hseconds = int((elap - minutes*60.0 - seconds)*100)
            self.timestr.set('%02d:%02d:%02d' % (minutes, seconds, hseconds))
    
        def Start(self):
            if not self._run:
                self._start = time.time() - self._timeelapsed
                self._update()
                self._run = 1
    
        def Stop(self):
            if self._run:
                self.after_cancel(self._timer)
                self._timeelapsed = time.time() - self._start
                self._setTime(self._timeelapsed)
                self._run = 0
    
        def Reset(self):
            self._start = time.time()
            self._timeelapsed = 0.0
            self._setTime(self._timeelapsed)
    
    
    def main():
        root = Tk()
        sw = StopWatch(root)
        sw.pack(side=TOP)
        Button(root, text='Start!', command=sw.Start).pack(side=LEFT)
        Button(root, text='Stop!', command=sw.Stop).pack(side=LEFT)
        Button(root, text='Reset!!!', command=sw.Reset).pack(side=LEFT)
        Button(root, text='Quit!!!', command=root.quit).pack(side=LEFT)
    
        root.mainloop()
    
    if __name__ == '__main__':
            main()
    

    【讨论】:

      猜你喜欢
      • 2020-08-29
      • 2015-11-23
      • 2021-04-29
      • 2021-07-24
      • 2013-06-22
      • 2022-01-01
      • 2015-11-20
      • 2018-08-05
      • 1970-01-01
      相关资源
      最近更新 更多