【问题标题】:Trying to understand why my stopwatch code is doing nothing (Python)试图理解为什么我的秒表代码什么都不做(Python)
【发布时间】:2020-07-30 04:56:11
【问题描述】:

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

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

我被难住了——当我按下任一按钮时都没有任何反应,而且我没有收到错误代码,所以我不知道为什么它不起作用。

我只有在按下停止后才会在框中看到任何东西,而且总是“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】:

您的代码有几个问题。

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

一般来说,事件驱动程序不会按照严格的时间表运行。你可以使用root.after()让它在一定时间后执行回调,但不能保证这个时间是准确的。

所以我的建议是:

  • 保存启动秒表的时间。
  • 使用每秒运行的after 回调。
  • 在该回调中,获取当前时间并从中减去开始时间。显示差异。
  • 请注意,在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 新手,最好从可以简单地从命令行调用的脚本开始(ms-windows 上的cmd.exe)。这些通常更容易读写,因为它们具有大部分线性控制流。在我的网站上,我有一个 article 关于两个等效程序,一个是简单的命令行脚本,另一个是 tkinter GUI。您可以在那里看到后者比前者涉及更多。

【讨论】:

  • 哇,这表明我几乎没有触及 Python 的表面。就上下文而言,这是我尝试写的第二个超过几行的东西(第一个是一个 GUI 计算器,它主要按预期工作,可能会被简化)。非常感谢您抽出宝贵的时间做出如此详细的回应——在我完全理解之前,我还有很多东西要研究。
猜你喜欢
  • 2011-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-30
  • 1970-01-01
  • 2017-11-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多