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

试图理解为什么我的秒表代码什么都不做(Python),python,tkinter,stopwatch,Python,Tkinter,Stopwatch,我试图编写python代码,使用tkinter在输入框中显示秒表 我的想法是使用递归函数,使用time.sleep(1)每秒向框中添加1 我被难住了——当我按下任何一个按钮时都不会发生任何事情,而且我没有得到错误代码,所以我不知道为什么它不工作 我唯一一次从盒子里拿东西是在按下停止键之后,它总是“00:00:00” 从tkinter导入* 导入时间 root=Tk() 根标题(“秒表”) #显示秒表的框 框=条目(根,宽度=20,边框宽度=5) box.grid(行=0,列=0) #在框中显示秒

我试图编写python代码,使用tkinter在输入框中显示秒表

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

我被难住了——当我按下任何一个按钮时都不会发生任何事情,而且我没有得到错误代码,所以我不知道为什么它不工作

我唯一一次从盒子里拿东西是在按下停止键之后,它总是“00:00:00”

从tkinter导入*
导入时间
root=Tk()
根标题(“秒表”)
#显示秒表的框
框=条目(根,宽度=20,边框宽度=5)
box.grid(行=0,列=0)
#在框中显示秒表
def show_timer():
全局小时、分钟、秒、计时器
计时器=str(小时)。zfill(2)+“:”+str(分钟)。zfill(2)+“:”+str(秒)。zfill(2)
框。删除(0,结束)
框。插入(0,计时器)
#check=1允许秒表运行
def设置检查(i):
全局检查
检查=i
退票
#秒表的实际功能
def秒表():
全局检查,小时、分钟、秒
如果检查==1:
时间。睡眠(1)
如果整数(秒)<59:
秒+=1
返回秒
elif分钟<59:
分钟+=1
秒=0
返回分钟,秒
其他:
小时+=1
分钟=0
秒=0
返回小时、分钟、秒
显示计时器()
秒表
其他:
显示计时器()
def start():
全球小时、分钟、秒
小时,分钟,秒=0,0,0
返回小时、分钟、秒
显示计时器()
设置检查(1)
秒表
def stop():
设置检查(0)
秒表
启动按钮=按钮(root,text=“start”,command=start)
停止按钮=按钮(root,text=“stop”,command=stop)
开始按钮网格(行=1,列=0)
停止按钮网格(行=2,列=0)
root.mainloop()

您的代码有几个问题

  • 从回调函数调用
    time.sleep()
    会中断
    tkinter
    事件循环,使GUI无响应
  • 不建议使用tkinter导入的
    *
    。为避免名称空间污染,请使用例如
    将tkinter导入为tk
  • 您可以从
    开始
    返回
    (=退出函数),而不做任何操作
  • 您的函数不需要
    return
    语句;您似乎没有使用返回的值
  • stopwatch
    中的内部
    if
    -语句的所有三个分支调用
    return
    ,因此不能递归调用
    stopwatch
    。那可能不是你想要的
  • 这是一件好事,因为来自回调的递归调用也会中断事件循环
  • 当您想要修改变量时,只需要使用
    global
    。例如,
    show\u timer
    不需要
    global
    。(顺便说一句,您可以修改容器类型的内容,如
    list
    dict
    ,而无需使用
    global
  • 全局上下文中不存在您指示为
    global
    的名称
通常,事件驱动的程序不会按照严格的时间表运行。您可以使用
root.after()
使其在特定时间后执行回调,但不能保证这个时间是准确的

因此,我建议:

  • 节省启动秒表的时间
  • 使用每秒运行的
    回调
  • 在该回调中,获取当前时间并从中减去开始时间。显示差异
  • 请注意,在回调之后的
    结束时,您必须重新注册它以保持其运行。(除非按下停止按钮
在我的tkinter程序中,我喜欢将所有状态保存在
types.SimpleNamespace
中,以明确这是程序状态。 以下是此更改的工作版本:

import time
import types
import tkinter as tk


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


def stop():
    state.run = False
    state.starttime = None
    box.delete(0, tk.END)


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


def display():
    difference = int(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)


if __name__ == '__main__':
    # Create program state
    state = types.SimpleNamespace()
    state.starttime = None
    state.run = False
    # Create widgets.
    root = tk.Tk()
    root.title("Stopwatch")
    root.attributes('-type', 'dialog')
    # box to display stopwatch
    box = tk.Entry(root, width=20, borderwidth=5)
    box.grid(row=0, column=0)
    start_button = tk.Button(root, text="Start", command=start)
    stop_button = tk.Button(root, text="Stop", command=stop)
    start_button.grid(row=1, column=0)
    stop_button.grid(row=2, column=0)
    # Run the GUI
    root.mainloop()
编辑


如果您是Python新手,那么最好从可以从命令行调用的脚本开始(
cmd.exe
在ms windows上)在我的网站上,我有两个相当的程序,一个是简单的命令行脚本,另一个是
tkinter
GUI。你可以看到后者比前者更复杂。

return
留下了当前的乐趣Action调用,因此您的
def start(…
什么都不做。仔细阅读《魔兽世界》,就会发现我几乎没有触及Python的表面。对于上下文,这是我尝试编写的第二件超过几行的东西(第一件是一个GUI计算器,它主要按照预期工作,可能可以简化).我非常感谢你花了这么多时间对我的问题做出如此详细的答复-在我完全理解之前,我还有很多事情要研究。
import time
import types
import tkinter as tk


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


def stop():
    state.run = False
    state.starttime = None
    box.delete(0, tk.END)


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


def display():
    difference = int(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)


if __name__ == '__main__':
    # Create program state
    state = types.SimpleNamespace()
    state.starttime = None
    state.run = False
    # Create widgets.
    root = tk.Tk()
    root.title("Stopwatch")
    root.attributes('-type', 'dialog')
    # box to display stopwatch
    box = tk.Entry(root, width=20, borderwidth=5)
    box.grid(row=0, column=0)
    start_button = tk.Button(root, text="Start", command=start)
    stop_button = tk.Button(root, text="Stop", command=stop)
    start_button.grid(row=1, column=0)
    stop_button.grid(row=2, column=0)
    # Run the GUI
    root.mainloop()