试图理解为什么我的秒表代码什么都不做(Python)

问题描述 投票:-1回答:1

我正在尝试编写python代码,该代码将使用tkinter在输入框中显示秒表。

我的想法是使用递归函数,使用time.sleep(1)每秒将1加到框中。

我很困惑-当我按下任一按钮时都什么也没发生,并且我没有收到错误代码,所以我不知道为什么它不起作用。

我唯一获得框中任何内容的时间是在按下Stop之后,它始终是“ 00:00:00”。

from tkinter import *
import time


root = Tk()
root.title("Stopwatch")

#box to display stopwatch
box = Entry(root, width = 20, borderwidth = 5)
box.grid(row = 0, column = 0)

#displays stopwatch in the box
def show_timer():
    global hrs, mins, secs, timer
    timer = str(hrs).zfill(2) + ":" + str(mins).zfill(2) + ":" + str(secs).zfill(2)
    box.delete(0, END)
    box.insert(0, timer)

#check = 1 allows the stopwatch to run
def set_check(i):
    global check
    check = i
    return check

#actual function for stopwatch
def stopwatch():
    global check, hrs, mins, secs
    if check == 1:
        time.sleep(1)
        if int(secs) < 59:
            secs += 1
            return secs
        elif mins < 59:
            mins += 1
            secs = 0
            return mins, secs
        else:
            hrs += 1
            mins = 0
            secs = 0
            return hrs, mins, secs
        show_timer()
        stopwatch()
    else:
        show_timer()


def start():
    global hrs, mins, secs
    hrs, mins, secs = 0, 0, 0
    return hrs, mins, secs
    show_timer()
    set_check(1)
    stopwatch()

def stop():
    set_check(0)
    stopwatch()



start_button = Button(root, text = "Start", command = start)
stop_button = Button(root, text = "Stop", command = stop)

start_button.grid(row = 1, column = 0)
stop_button.grid(row = 2, column = 0)

root.mainloop()
python tkinter stopwatch
1个回答
0
投票

您的代码有几个问题。

  • 从回调函数调用time.sleep()会中断tkinter事件循环,从而使GUI无响应。
  • from tkinter import *不推荐。为了避免命名空间污染,请使用例如import tkinter as tk
  • return(=退出功能)没有采取任何措施。
  • 您的函数不需要start语句;您似乎没有使用返回的值。
  • return中内部if语句的所有三个分支都调用stopwatch,因此永远不能递归调用return。那可能不是您想要的。
  • 这是一件好事,因为从回调中进行递归调用也会中断事件循环。
  • 您只需要使用stopwatch即可修改变量。所以例如global不需要show_timer
  • 您指定为global的名称在全局上下文中不存在。

通常,事件驱动程序的运行时间表并不严格。您可以使用global使它在一定时间后执行回调,但是不能保证这段时间是正确的。

所以我建议是:

  • 节省您启动秒表的时间。
  • 使用每秒运行的root.after()回调。
  • 在该回调中,获取当前时间并从中减去开始时间。显示差异。
  • 注意,在after回调的末尾,您必须重新注册它才能使其继续运行。 (除非按下了停止按钮。

在我的tkinter程序中,我喜欢将所有状态都保留在after中,以明确表明这是程序状态。因此,在types.SimpleNamespace调用之前,我会这样做:

mainloop

然后您可以在回调函数中简单地执行例如

 state = type.SimpleNamespace()
 state.starttime = None
 state.run = False

这里是工作版本:

def start():
    start.starttime = time.time()
    state.run = True
    display()
    root.after(1000, update)


def update():
    display()
    if state.run:
        root.after(1000, update)


def display():
    difference = time.time() - state.starttime
    minutes, seconds = divmod(difference, 60)
    hours, minutes = divmod(minutes, 60)
    display = "{:02d}:{:02d}:{:02d}".format(hours, minutes, seconds)
    box.delete(0, tk.END)
    box.insert(0, display)
© www.soinside.com 2019 - 2024. All rights reserved.