Tkinter locking into function

Asked

Viewed 262 times

0

I am making a mini-program to be used in the working hours/study style the Pomodoro method. I made it very simple, fast, but when I press to start, the program hangs exactly the time that was put and only comes back when everything ended, to try to find the error I left with 3 seconds each interval and time of service, then it stands still until it finishes everything. There are some visual changes that should occur on the tele, as show the cycles and what stage is, but nothing moves, and only comes back when everything Zera. Follow the code below:

from tkinter import *
from time import sleep

# Action
def pomodoro():
    lb_acao['text'] = 'Pomodori'
    lb_acao['bg'] = 'red'
    qt_ciclos = int(ed_ciclos.get())

    while qt_ciclos >= 0:
        lb_ciclos_restantes['text'] = qt_ciclos
        sleep(3)

        lb_acao['text'] = 'Intervalo'
        lb_acao['bg'] = 'green'
        sleep(3)

        lb_acao['text'] = 'Pomodori'
        lb_acao['bg'] = 'red'

        qt_ciclos -= 1

win = Tk()

# Components
lb1 = Label(win, text='Tempo útil: ')
ed_tempo = Entry(win)

lb2 = Label(win, text='Tempo de intervalo: ')
ed_intervalo = Entry(win)

lb3 = Label(win, text='Quantidade de ciclos: ')
ed_ciclos = Entry(win)

btn = Button(win, text='Começar', command=pomodoro)

lb4 = Label(win, text='Ciclos restantes:')
lb_ciclos_restantes = Label(win, text='0')

lb5 = Label(win, text='Modo:')
lb_acao = Label(win, text='Preparado')

lb6 = Label(win, text='Tempo:')
lb_time = Label(win)

# GUI
lb1.grid(row=0, column=0)
ed_tempo.grid(row=0, column=1)

lb2.grid(row=1, column=0)
ed_intervalo.grid(row=1, column=1)

lb3.grid(row=2, column=0)
ed_ciclos.grid(row=2, column=1)

btn.grid(row=3, column=0, columnspan=2, sticky=W+E)


lb4.grid(row=4, column=0)
lb_ciclos_restantes.grid(row=4, column=1)
lb5.grid(row=5, column=0)
lb_acao.grid(row=5, column=1)
lb6.grid(row=6, column=0)
lb_time.grid(row=6, column=1)

# Program
win.mainloop()

So, this is a characteristic of Tkinter, which doesn’t allow you to keep fiddling with your look constantly. Or is there something wrong that I’m not noticing?

Thanks....

1 answer

0


This happens because your program is synchronous. That means it only does one thing at a time. When you call sleep, the program stops to perform to sleep that certain time, and while sleeping it neither updates the screen nor listens to the interface to know if the user gave any command; in this, it gets stuck, despite coming back when the time of "slept".

The solution is to use the function after of Tk. You pass her the number of milliseconds you want to wait and a function; Tkinter then executes that function after the given number of milliseconds.

That means you have to split your function pomodoro in some parts, so you can wait between them. As we also have to remember in which cycle we are in different functions, we added a global variable. Here, I called it ciclo_atual, and kept the original code waiting 3s:

from tkinter import *

# Quando o botão é clicado, resetamos o contador de ciclo atual
# e iniciamos o primeiro ciclo.
def pomodoro():
    global ciclo_atual
    ciclo_atual = 0
    iniciar_ciclo()

# Quando iniciamos um ciclo, verificamos se o contador extrapolou
# a quantidade de ciclos desejada. Se não, chamamos a função
# iniciar_intervalo depois de 3000 milisegundos.
def iniciar_ciclo():
    global ciclo_atual
    lb_acao['text'] = 'Pomodori'
    lb_acao['bg'] = 'red'
    qt_ciclos = int(ed_ciclos.get())
    lb_ciclos_restantes['text'] = qt_ciclos - ciclo_atual

    if ciclo_atual < qt_ciclos:
        ciclo_atual += 1
        win.after(3000, iniciar_intervalo)

# Ao iniciar o intervalo, atualizamos a interface e chamamos
# novamente a função iniciar_ciclo depois de 3000 ms.
def iniciar_intervalo():
    lb_acao['text'] = 'Intervalo'
    lb_acao['bg'] = 'green'
    win.after(3000, iniciar_ciclo)


win = Tk()

# Components
lb1 = Label(win, text='Tempo útil: ')
ed_tempo = Entry(win)

lb2 = Label(win, text='Tempo de intervalo: ')
ed_intervalo = Entry(win)

lb3 = Label(win, text='Quantidade de ciclos: ')
ed_ciclos = Entry(win)

btn = Button(win, text='Começar', command=pomodoro)

lb4 = Label(win, text='Ciclos restantes:')
lb_ciclos_restantes = Label(win, text='0')

lb5 = Label(win, text='Modo:')
lb_acao = Label(win, text='Preparado')

lb6 = Label(win, text='Tempo:')
lb_time = Label(win)

# GUI
lb1.grid(row=0, column=0)
ed_tempo.grid(row=0, column=1)

lb2.grid(row=1, column=0)
ed_intervalo.grid(row=1, column=1)

lb3.grid(row=2, column=0)
ed_ciclos.grid(row=2, column=1)

btn.grid(row=3, column=0, columnspan=2, sticky=W+E)


lb4.grid(row=4, column=0)
lb_ciclos_restantes.grid(row=4, column=1)
lb5.grid(row=5, column=0)
lb_acao.grid(row=5, column=1)
lb6.grid(row=6, column=0)
lb_time.grid(row=6, column=1)

# Program
win.mainloop()
  • 1

    Wow, really cool, I didn’t know this function of Tkinter. Excellent, my Sleep exchange was very suspicious of being the problem kkkk. I’m gonna do a few extra things on him, but there you go. The people who want to make their tasks more productive, already have a program to let rolling while working/ study. Thanks!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.