Python – Temporizador de cuenta regresiva dentro de un canvas tkinter

Hola, me gustaría crear un temporizador de cuenta regresiva dentro de una subrutina que luego se muestra en el canvas. No estoy completamente seguro de por dónde empezar. Lo investigué y pude hacer uno con la función time.sleep (x) pero ese método congela todo el progtwig, que no es lo que busco. . También busqué las otras preguntas aquí acerca de un temporizador e intenté incorporarlas a mi progtwig, pero aún no pude tener ningún éxito.

TLDR; Quiero crear un temporizador de cuenta regresiva con una cuenta regresiva de 60 segundos y se muestra en un canvas y luego hacer que haga algo cuando el temporizador llegue a 0.

¿Alguien puede apuntarme en la dirección correcta?

Gracias por adelantado.

EDITAR: Con las sugerencias proporcionadas traté de ponerlas en el progtwig sin mucha suerte.

No estoy seguro si hay un error importante en este código o si es simplemente un error. El error que recibo cuando lo ejecuto está debajo del código.

Esta es la parte del código en la que quiero que aparezca el temporizador:

def main(): #First thing that loads when the program is executed. global window global tkinter global canvas global cdtimer window = Tk() cdtimer = 60 window.title("JailBreak Bob") canvas = Canvas(width = 960, height = 540, bg = "white") photo = PhotoImage(file="main.gif") canvas.bind("", buttonclick_mainscreen) canvas.pack(expand = YES, fill = BOTH) canvas.create_image(1, 1, image = photo, anchor = NW) window.mainloop() def buttonclick_mainscreen(event): pressed = "" if event.x >18 and event.x  359 and event.y 18 and event.x  421 and event.y 18 and event.x  477 and event.y < 517 : pressed = 3 if pressed == 1 : gamescreen() if pressed == 2 : helpscreen() if pressed == 3 : window.destroy() def gamescreen(): photo = PhotoImage(file="gamescreen.gif") canvas.bind("", buttonclick_gamescreen) canvas.pack(expand = YES, fill = BOTH) canvas.create_image(1, 1, image = photo, anchor = NW) game1 = PhotoImage(file="1.gif") canvas.create_image(30, 65, image = game1, anchor = NW) e1 = Entry(canvas, width = 11) e2 = Entry(canvas, width = 11) canvas.create_window(390, 501, window=e1, anchor = NW) canvas.create_window(551, 501, window=e2, anchor = NW) canvas.after(1, gamescreen) window.mainloop() def cdtimer(): canvas.delete(ALL) global cdtimer cdtimer -= 1 canvas.create_text(510, 6, text=cdtimer, font="Ubuntu 29 bold", anchor = NW) if cdtimer == 0: scorescreen() else: canvas.after(1000, gamescreen) main() 

Error MSG:

 Exception in Tkinter callback Traceback (most recent call last): File "/usr/lib/python3.2/tkinter/__init__.py", line 1402, in __call__ return self.func(*args) File "/usr/lib/python3.2/tkinter/__init__.py", line 490, in callit func(*args) File "/home/ppppwn3d/workspace/Python/JailBreakBob/JailBreakBob.py", line 50, in gamescreen e1 = Entry(canvas, width = 11) File "/usr/lib/python3.2/tkinter/__init__.py", line 2372, in __init__ Widget.__init__(self, master, 'entry', cnf, kw) File "/usr/lib/python3.2/tkinter/__init__.py", line 1952, in __init__ cnf = _cnfmerge((cnf, kw)) File "/usr/lib/python3.2/tkinter/__init__.py", line 71, in _cnfmerge if isinstance(cnfs, dict): RuntimeError: maximum recursion depth exceeded while calling a Python object 

Esta es una expansión de la respuesta de Oakley. Demuestra cómo mostrar el tiempo en un canvas y cómo arrancar todo:

 from tkinter import * root = Tk() canvas = Canvas(root) canvas.pack() time = 60 def tick(): # You have to clear the canvas each time the clock updates # (otherwise it writes on top of the old time). Since the # time is the only thing in the canvas, delete(ALL) works # perfectly (if it wasn't however, you can delete the id # that goes with the clock). canvas.delete(ALL) # I have to declare time as a global because I'm not using # a class (otherwise, I could do something like self.time -= 1) global time time -= 1 # You can place the time wherever in the canvas # (I chose 10,10 for the example) canvas.create_text(10, 10, text=time) if time == 0: do_something() else: canvas.after(1000, tick) canvas.after(1, tick) root.mainloop() 

La secuencia de comandos realiza una cuenta regresiva desde 60 segundos (mostrando el tiempo restante a medida que avanza) y, cuando llega a 0, llama a do_something.

Quieres usar el método after . La lógica es algo como esto:

 def update_clock(self): self.counter -= 1 if self.counter == 0 : do_something() else: self.after(1000, self.update_clock) 

Lo anterior restará uno del contador. Si el contador es cero hace algo especial. De lo contrario, se progtwig para ejecutarse de nuevo en un segundo.

¿Es posible que desee intentar enhebrar?

 import thread import time def myFunct(): sec = 60 n = 1 for i in range(sec/n): updateClock() time.sleep(n) finalFunct() thread.start_new_thread(myFunct, ()) 

Simplemente cambie en sec a la cantidad inicial (en segundos), y n al intervalo en el que desea que se actualice (en segundos).