파이썬/파이썬(python) 중급

[28-6 파이썬] tkinter 타이머 만들기, after_cancel() (최종)

Olivia-BlackCherry 2022. 9. 17. 19:45

28번째 기록은  tkinter로 타이머 만들기이다. 

이제까지의 코드에 대한 설명과 과정은  28-1~28-5를 참고하면 된다.

 

오늘은 타이머를 커스터마이징해보자.

 

아래와 같이 타이머를 연속으로 작동한다고 하자.

총 8회기 카운트 다운

1회

1: 20분

2: 5분

 

2회

1: 20분

2: 5분

 

3회

1: 20분

2: 5분

 

4회

1: 20분

2: 25분

 

이렇게 코드를 짜면 에러가 발생한다.

중간 회기의 카운트 다운은 화면에 보이지 않고,

마지막 회기 카운트 다운만 보인다.

def start_timer():
    global reps
    while reps<4:
        count_down(25*1)
        reps+=1

        if 0< reps <4:
            count_down(5*1)
        elif reps==4:
            count_down(20*1)

 

따라서, 아래와 같이 코드를 수정한다.

start_timer 함수에서 횟수에 따라 타이머가 작동하는 시간을 지정한 후,

count_down 함수에서 해당 순서에 타이머가 모두 카운트다운되고 나면, 다음 회기로 넘어가 다시 카운트 다운하도록  

전역변수 reps를 이용하고, start_timer함수를 다시 호출한다.


from tkinter import *
import math

# ---------------------------- CONSTANTS ------------------------------- #
GREEN = "#9bdeac"
YELLOW = "#f7f5dd"
PINK = "#EBC7E8"
WORK_TIME = 25
REST_TIME = 5
FREE_TIME = 20

reps=0
# ---------------------------- TIMER RESET ------------------------------- #
def count_down(number):
    minute = math.floor(number/60)
    second = number % 60
    if second ==0 or second<10:
        second=f"0{second}"

    canvas.itemconfig(time_text, text=f"{minute}:{second}")
    if number>0:
        window.after(1000, count_down, number-1)
    else:
        start_timer()
# ---------------------------- TIMER MECHANISM ------------------------------- #
def start_timer():
    global reps
    reps +=1
    if reps % 8 == 0:
        count_down(FREE_TIME*60)
    elif reps %2 ==1:
        count_down(WORK_TIME*60)
    else:
        count_down(REST_TIME*60)

window = Tk()
window.title("dog_time")
window.config(padx=100, pady=50, bg=YELLOW)


canvas = Canvas(width=400, height=300, bg=PINK, highlightthickness=0)
dog_img = PhotoImage(file="dog.png")
canvas.create_image(200, 140, image=dog_img)
time_text =canvas.create_text(190,30, text="00:00", fill = "purple", font =("Courier", 40, "bold"))
canvas.grid(row=1, column=1)

label_time = Label(text="Timer", font= ("Courier", 50, "bold"), fg=GREEN, bg= YELLOW)
label_time.grid(row=0, column=1)

button_start = Button(text="Start", font= ("Courier", 20, "bold"), fg="black", bg=YELLOW, highlightthickness=0, command=start_timer)
button_start.grid(row=2, column=0)

button_reset = Button(text="Reset", font=("Courier", 20, "bold"), fg="black", bg=YELLOW, highlightthickness=0)
button_reset.grid(row=2, column=2)

check = Label(text="V", fg=GREEN, bg=YELLOW)
check.grid(row=3, column=1)



window.mainloop()

 

이번에는 

카운트 다운 목적(일하기, 잠깐 쉬기, 장기 휴식)이 바뀔 때마다, 

제목(timer)이 바뀌도록 구성해보자.

config()메소드를 사용하며

글자 내용은 text에, 글자 색깔은 fg 파라미터에 쓴다.

from tkinter import *
import math

# ---------------------------- CONSTANTS ------------------------------- #
GREEN = "#9bdeac"
YELLOW = "#f7f5dd"
PINK = "#EBC7E8"
RED = "#e7305b"
WORK_TIME = 1
REST_TIME = 0.5
FREE_TIME = 0.1

reps=0
# ---------------------------- TIMER RESET ------------------------------- #
def count_down(number):
    minute = math.floor(number/60)
    second = number % 60
    if second ==0 or second<10:
        second=f"0{second}"

    canvas.itemconfig(time_text, text=f"{minute}:{second}")
    if number>0:
        window.after(1000, count_down, number-1)
    else:
        start_timer()
# ---------------------------- TIMER MECHANISM ------------------------------- #
def start_timer():
    global reps
    reps +=1
    if reps % 8 == 0:
        label_time.config(text="노는 시간~", fg=PINK)
        count_down(FREE_TIME*60)
    elif reps %2 ==1:
        label_time.config(text="일하자!", fg=RED)
        count_down(int(WORK_TIME*60))
    else:
        label_time.config(text="잠깐 쉬자!", fg=GREEN)
        count_down(int(REST_TIME*60))

window = Tk()
window.title("dog_time")
window.config(padx=100, pady=50, bg=YELLOW)


canvas = Canvas(width=400, height=300, bg=PINK, highlightthickness=0)
dog_img = PhotoImage(file="dog.png")
canvas.create_image(200, 140, image=dog_img)
time_text =canvas.create_text(190,30, text="00:00", fill = "purple", font =("Courier", 40, "bold"))
canvas.grid(row=1, column=1)

label_time = Label(text="Timer", font= ("Courier", 50, "bold"), fg=GREEN, bg= YELLOW)
label_time.grid(row=0, column=1)

button_start = Button(text="Start", font= ("Courier", 20, "bold"), fg="black", bg=YELLOW, highlightthickness=0, command=start_timer)
button_start.grid(row=2, column=0)

button_reset = Button(text="Reset", font=("Courier", 20, "bold"), fg="black", bg=YELLOW, highlightthickness=0)
button_reset.grid(row=2, column=2)

check = Label(text="V", fg=GREEN, bg=YELLOW)
check.grid(row=3, column=1)



window.mainloop()

 

1회기가 끝날 때마다 체크박스를 표시한다.

if elif 구문을 쓰거나,

def count_down(number):
    minute = math.floor(number/60)
    second = number % 60
    if second ==0 or second<10:
        second=f"0{second}"

    canvas.itemconfig(time_text, text=f"{minute}:{second}")
    if number>0:
        window.after(1000, count_down, number-1)
    else:
        start_timer()

        if reps ==2:
            check.config(text="V")
        elif reps ==4:
            check.config(text="V V")
        elif reps ==6:
            check.config(text="V V V")
        elif reps ==8:
            check.config(text="V V V V")

 

반복 구문을 활용한 후, 문자열 연산을 활용할 수 있다.

def count_down(number):
    minute = math.floor(number/60)
    second = number % 60
    if second ==0 or second<10:
        second=f"0{second}"

    canvas.itemconfig(time_text, text=f"{minute}:{second}")
    if number>0:
        window.after(1000, count_down, number-1)
    else:
        start_timer()
        if reps%2 ==0:
            check_box =''
            for i in range(int(reps/2)):
                check_box += "V"
                check.config(text=check_box)

 

 

리셋하면 카운트 다운이 멈추도록 만들자.

먼저 count_down함수에서 after() 구문을 변수로 지정한다.

if number>0:
    timer = window.after(1000, count_down, number-1)

 

 

그리고, timer를 전역함수로 만든다.

timer= None
# ---------------------------- TIMER RESET ------------------------------- #
def count_down(number):
    global timer
    minute = math.floor(number/60)
    second = number % 60
    if second ==0 or second<10:
        second=f"0{second}"

    canvas.itemconfig(time_text, text=f"{minute}:{second}")
    if number>0:
        timer = window.after(1000, count_down, number-1)
    else:
        start_timer()
        if reps%2 ==0:
            check_box =''
            for i in range(int(reps/2)):
                check_box += "V"
                check.config(text=check_box)

 

 

reset함수를 만든다.

timer = after(시간, 실행할 함수,...)

after_cancel(timer)

--> 타이머를 정지한다.

def reset():
    window.after_cancel(timer)

 

 

reset버튼을 누르면 카운트다운이 멈추게 한다.

button_reset = Button(text="Reset", font=("Courier", 20, "bold"), fg="black", bg=YELLOW, highlightthickness=0, command=reset)

 

 

reset버튼을 눌렀을 때 title은 timer로, 시간은 00:00으로, 체크박스는 공란으로 만든다.

def reset():
    window.after_cancel(timer)
    label_time.config(text="Timer")
    canvas.itemconfig(time_text, text="00:00")
    check.config(text="")

 

 

마지막으로 reps를 0으로 초기화시킨다.

global reps
reps = 0

 

 

<최종코드>

from tkinter import *
import math

# ---------------------------- CONSTANTS ------------------------------- #
GREEN = "#9bdeac"
YELLOW = "#f7f5dd"
PINK = "#EBC7E8"
RED = "#e7305b"
WORK_TIME = 0.2
REST_TIME = 0.5
FREE_TIME = 0.1

reps=0
timer= None
# ---------------------------- TIMER RESET ------------------------------- #
def count_down(number):
    global timer
    minute = math.floor(number/60)
    second = number % 60
    if second ==0 or second<10:
        second=f"0{second}"

    canvas.itemconfig(time_text, text=f"{minute}:{second}")
    if number>0:
        timer = window.after(1000, count_down, number-1)
    else:
        start_timer()
        if reps%2 ==0:
            check_box =''
            for i in range(int(reps/2)):
                check_box += "V"
                check.config(text=check_box)

# ---------------------------- TIMER MECHANISM ------------------------------- #
def start_timer():
    global reps
    reps +=1
    if reps % 8 == 0:
        label_time.config(text="노는 시간~", fg=PINK)
        count_down(int(FREE_TIME*60))
    elif reps %2 ==1:
        label_time.config(text="일하자!", fg=RED)
        count_down(int(WORK_TIME*60))
    else:
        label_time.config(text="잠깐 쉬자!", fg=GREEN)
        count_down(int(REST_TIME*60))

# ---------------------------- UI SETUP ------------------------------- #
def reset():
    window.after_cancel(timer)
    label_time.config(text="Timer")
    canvas.itemconfig(time_text, text="00:00")
    check.config(text="")
    global reps
    reps = 0

window = Tk()
window.title("dog_time")
window.config(padx=100, pady=50, bg=YELLOW)


canvas = Canvas(width=400, height=300, bg=PINK, highlightthickness=0)
dog_img = PhotoImage(file="dog.png")
canvas.create_image(200, 140, image=dog_img)
time_text =canvas.create_text(190,30, text="00:00", fill = "purple", font =("Courier", 40, "bold"))
canvas.grid(row=1, column=1)

label_time = Label(text="Timer", font= ("Courier", 50, "bold"), fg=GREEN, bg= YELLOW)
label_time.grid(row=0, column=1)

button_start = Button(text="Start", font= ("Courier", 20, "bold"), fg="black", bg=YELLOW, highlightthickness=0, command=start_timer)
button_start.grid(row=2, column=0)

button_reset = Button(text="Reset", font=("Courier", 20, "bold"), fg="black", bg=YELLOW, highlightthickness=0, command=reset)
button_reset.grid(row=2, column=2)

check = Label(fg=GREEN, bg=YELLOW)
check.grid(row=3, column=1)



window.mainloop()