Python 中是否有一种方法可以通过单击按钮来更改函数的工作方式

时间:2021-02-23 16:27:57

标签: python tkinter

我用 Python 编写了这个简单的程序,它由 2 个按钮(开始和重置)以及 00:00 计时器的画布组成,它的作用是当您单击开始时,时间从(25 分钟)开始倒计时) 直到到达 00:00 并将 label_text 从“Work”更改为“Break”,倒计时再次从(5 分钟到 00:00)开始,并将 label_text 从“Break”更改回“Work”,一切正常但是,我的问题是:如果我多次单击“开始”,两个倒计时同时工作,我需要的是,当我单击“开始”时,除非单击“重置”按钮,否则我将无法再次单击它.

我可以使用 button["state"] = DISABLED 修复它,但它没有帮助,如果您知道任何其他方式,我将非常感谢您的帮助,在此先非常感谢您。

这是我的代码:

from tkinter import *
import math
# ---------------------------- CONSTANTS ------------------------------- #
PINK = "#e2979c"
RED = "#e7305b"
GREEN = "#9bdeac"
YELLOW = "#f7f5dd"
FONT_NAME = "Courier"
WORK_MIN = 25
SHORT_BREAK_MIN = 5
LONG_BREAK_MIN = 20
reps = 0
timer = None

# ---------------------------- TIMER RESET ------------------------------- #
def reset_timer():
    window.after_cancel(timer)
    checkmark_label.config(text="")
    canvas.itemconfig(time_text, text="00:00")
    timer_label.config(text="Timer")
    global reps
    reps = 0


# ---------------------------- TIMER MECHANISM ------------------------------- #
def start_timer():
    global reps
    reps += 1

    work_sec = WORK_MIN * 60
    short_break_sec = SHORT_BREAK_MIN * 60
    long_break_sec = LONG_BREAK_MIN * 60

    if reps % 8 == 0:
        count_down(long_break_sec)
        timer_label.config(text="Break", fg=RED)


    elif reps % 2 == 0:
        count_down(short_break_sec)
        timer_label.config(text="Break", fg=PINK)
        window.attributes('-topmost', 1)

    else:
        count_down(work_sec)
        timer_label.config(text="Work", fg=GREEN)
        window.attributes('-topmost', 0)

# ---------------------------- COUNTDOWN MECHANISM ------------------------------- #


def count_down(count):

    count_min =  math.floor(count / 60)
    count_sec = count % 60
    if count_sec == 0:
        count_sec = "00"
    elif count_sec > 0 and count_sec < 10:
        count_sec = f"0{count_sec}"
    canvas.itemconfig(time_text, text=f"{count_min}:{count_sec}")
    if count > 0:
        global timer
        timer = window.after(1000, count_down, count - 1)

    else:
        start_timer()
        marks = ""
        work_sessions = math.floor(reps/2)
        for _ in range(work_sessions):
            marks += "✔"
            checkmark_label.config(text=marks)



# ---------------------------- UI SETUP ------------------------------- #
window = Tk()
window.title("Pomodoro")
window.config(padx=100, pady=50, bg=YELLOW)


canvas = Canvas(width=200, height=224, bg=YELLOW, highlightthickness=0)
tomato_img = PhotoImage(file="tomato.png")
canvas.create_image(100, 112, image=tomato_img)
time_text = canvas.create_text(103, 130, text="00:00", fill="white", font=(FONT_NAME, 35, "bold"))
canvas.grid(column=2, row=2)


# Labels
timer_label = Label(text="Timer",bg=YELLOW, fg=GREEN, font=(FONT_NAME, 50, "bold"))
timer_label.grid(column=2, row=1)
checkmark_label = Label(fg=GREEN)
checkmark_label.grid(column=2, row=4)


# Buttons
start_button = Button(text="Start", bg=GREEN, width=11, height=2, borderwidth=0, command=start_timer)
start_button.grid(column=1, row=3)
reset_button = Button(text="Reset", bg=GREEN, width=11, height=2, borderwidth=0, command=reset_timer)
reset_button.grid(column=3, row=3)


window.mainloop()

1 个答案:

答案 0 :(得分:1)

我不知道你为什么遇到这个问题,但你需要的只是跟踪计时器是否已经在计数。为此,我创建了一个名为“is_counting”的全局变量,默认情况下为 False。当用户按下“开始”按钮时,它将此变量设置为 True。如果用户再次按下此按钮,程序将看到计时器已经在计数,并且不会启动新的计时器。这个解决方案超级简单,但很有效,而且效果很好。

已应用修复的代码:

from tkinter import *
import math
# ---------------------------- CONSTANTS ------------------------------- #
PINK = "#e2979c"
RED = "#e7305b"
GREEN = "#9bdeac"
YELLOW = "#f7f5dd"
FONT_NAME = "Courier"
WORK_MIN = 25
SHORT_BREAK_MIN = 5
LONG_BREAK_MIN = 20
reps = 0
timer = None
is_counting = False

# ---------------------------- TIMER RESET ------------------------------- #
def reset_timer():
    global is_counting
    is_counting = False

    window.after_cancel(timer)
    checkmark_label.config(text="")
    canvas.itemconfig(time_text, text="00:00")
    timer_label.config(text="Timer")
    global reps
    reps = 0


# ---------------------------- TIMER MECHANISM ------------------------------- #
def start_timer():
    # Checking if timer already exists. If it is,
    # this function won't do anything
    global is_counting
    if is_counting:
        return
    is_counting = True

    global reps
    reps += 1

    work_sec = WORK_MIN * 60
    short_break_sec = SHORT_BREAK_MIN * 60
    long_break_sec = LONG_BREAK_MIN * 60

    if reps % 8 == 0:
        count_down(long_break_sec)
        timer_label.config(text="Break", fg=RED)


    elif reps % 2 == 0:
        count_down(short_break_sec)
        timer_label.config(text="Break", fg=PINK)
        window.attributes('-topmost', 1)

    else:
        count_down(work_sec)
        timer_label.config(text="Work", fg=GREEN)
        window.attributes('-topmost', 0)

# ---------------------------- COUNTDOWN MECHANISM ------------------------------- #


def count_down(count):

    count_min =  math.floor(count / 60)
    count_sec = count % 60
    if count_sec == 0:
        count_sec = "00"
    elif count_sec > 0 and count_sec < 10:
        count_sec = f"0{count_sec}"
    canvas.itemconfig(time_text, text=f"{count_min}:{count_sec}")
    if count > 0:
        global timer
        timer = window.after(1000, count_down, count - 1)

    else:
        # Setting is_counting variable to False, because start_timer()
        # won't work when timer is already counting
        global is_counting
        is_counting = False
        start_timer()
        marks = ""
        work_sessions = math.floor(reps/2)
        for _ in range(work_sessions):
            marks += "✔"
            checkmark_label.config(text=marks)



# ---------------------------- UI SETUP ------------------------------- #
window = Tk()
window.title("Pomodoro")
window.config(padx=100, pady=50, bg=YELLOW)


canvas = Canvas(width=200, height=224, bg=YELLOW, highlightthickness=0)
tomato_img = PhotoImage(file="tomato.png")
canvas.create_image(100, 112, image=tomato_img)
time_text = canvas.create_text(103, 130, text="00:00", fill="white", font=(FONT_NAME, 35, "bold"))
canvas.grid(column=2, row=2)


# Labels
timer_label = Label(text="Timer",bg=YELLOW, fg=GREEN, font=(FONT_NAME, 50, "bold"))
timer_label.grid(column=2, row=1)
checkmark_label = Label(fg=GREEN)
checkmark_label.grid(column=2, row=4)


# Buttons
start_button = Button(text="Start", bg=GREEN, width=11, height=2, borderwidth=0, command=start_timer)
start_button.grid(column=1, row=3)
reset_button = Button(text="Reset", bg=GREEN, width=11, height=2, borderwidth=0, command=reset_timer)
reset_button.grid(column=3, row=3)


window.mainloop()