Saltar al contenido

TKinter – ¿Cómo detener un bucle con un botón de parada?

Solución:

Hay varias cosas mal en su código. Primero que nada, no deberías usar time.sleep() en un programa de Tkinter porque interfiere con el mainloop(). En su lugar, normalmente se usa el método de widget universal .after() para programar una función para que se ejecute después de un retraso específico.

En segundo lugar, no está utilizando las variables globales correctamente. Cuando asigna un valor a una variable nombrada en una función, creará una variable local a menos que ese nombre haya sido declarado previamente global. Entonces, por ejemplo, tu stop() la función está creando una variable local llamada running y estableciendo su valor en 0, no cambiando el valor de la variable global con el mismo nombre.

La regla anterior no se aplica solo a hacer referencia (leer) al valor actual de una variable. Por eso estaba bien no haber declarado Freq y Dur globales en start().

Otro problema es con el sec % 1 == 0 en tus start() función. Algún valor % 1 es 0. Para comprobar el uso impar / uniforme sec % 2.

Aquí hay una versión funcional que también ha sido reformateada para seguir más de cerca la Guía de estilo de PEP 8 para código Python.

import Tkinter
import tkMessageBox
import time
import winsound

FREQ = 2500
DUR = 150

after_id = None
secs = 0

def beeper():
    global after_id
    global secs
    secs += 1
    if secs % 2 == 0:  # every other second
        winsound.Beep(FREQ, DUR)
    after_id = top.after(1000, beeper)  # check again in 1 second

def start():
    global secs
    secs = 0
    beeper()  # start repeated checking

def stop():
    global after_id
    if after_id:
        top.after_cancel(after_id)
        after_id = None

top = Tkinter.Tk()
top.title('MapAwareness')
top.geometry('200x100')

startButton = Tkinter.Button(top, height=2, width=20, text="Start",
                             command=start)
stopButton = Tkinter.Button(top, height=2, width=20, text="Stop",
                            command=stop)
startButton.pack()
stopButton.pack()
top.mainloop()

Tu código tiene top.mainloop() que tiene un while bucle que se ejecuta dentro de él y, además de eso, también tiene un bucle while dentro def start():. Entonces es como un bucle dentro del bucle.

Puede crear una función que haga lo que quiera para el cuerpo del bucle. Debería hacer exactamente una iteración del ciclo. Una vez hecho esto, necesita arreglarse para ser llamado nuevamente en el futuro usando after. Qué tan lejos en el futuro define qué tan rápido se ejecuta su ciclo.

Y luego puedes usar after_cancel para cancelar el evento. El siguiente código funcionó para mí

import Tkinter, tkMessageBox, time, winsound, msvcrt

Freq = 2500
Dur = 150

top = tkinter.Tk()
top.title('MapAwareness')
top.geometry('200x100') # Size 200, 200

def start():
    global job1
    if running == True:
        winsound.Beep(Freq, Dur)
        job1 = top.after(1000, start)  # reschedule event in 1 seconds

def stop():
    global job1
    top.after_cancel(job1)

startButton = tkinter.Button(top, height=2, width=20, text ="Start", command = start)
stopButton = tkinter.Button(top, height=2, width=20, text ="Stop", command = stop)

startButton.pack()
stopButton.pack()
#top.after(1000, start)
top.mainloop()
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *