Aplicación Mientras Loop Locks

Resuelto Husar asked hace 9 años • 3 respuestas

Llevo un tiempo golpeándome la cabeza con una aplicación en la que estoy trabajando. Después de muchas horas intentando depurar un problema en el que la interfaz se bloquea y no puede ocurrir nada más, descubrí que era el temido bucle While. Vea este ejemplo a continuación y ejecútelo. Cuando inicia el ciclo while haciendo clic en el botón, no puede hacer nada más en la pantalla. En este caso, es solo un simple botón de alerta que debe presionarse.

from Tkinter import *
import tkMessageBox

root = Tk()
root.geometry("450x250+300+300")
root.title("Raspberry PI Test")

def myloop():
    count = 0
    while (count < 500):
       print 'The count is:', count
       count = count + 1

    print "Good bye!"

def mymessage():
    tkMessageBox.showinfo(title="Alert", message="Hello World!")

buttonLoop = Button(root, text="Start Loop", command=myloop)
buttonLoop.place(x=5, y=15)

buttonMessage = Button(root, text="Start Loop", command=mymessage)
buttonMessage.place(x=85, y=15)


root.mainloop()

¿Cómo puedo tener un bucle que deba ejecutarse hasta que se complete un recuento y aún poder realizar otras tareas en mi aplicación? También debo tener en cuenta que probé lo mismo usando un hilo y no importa. La interfaz de usuario todavía está esperando que finalice el ciclo While antes de que puedas hacer algo.

Husar avatar Feb 21 '15 05:02 Husar
Aceptado

ahora que entiendo mejor lo que quieres (un cronómetro), recomendaría el comando root.after

from Tkinter import *
import tkMessageBox
import threading
import time
root = Tk()
root.geometry("450x250+300+300")
root.title("Raspberry PI Test")
print dir(root)
count = 0
def start_counter():
    global count
    count = 500
    root.after(1,update_counter)
def update_counter():
    global count
    count -= 1
    if count < 0:
        count_complete()
    else:
        root.after(1,update_counter)

def count_complete():
    print "DONE COUNTING!! ... I am now back in the main thread"
def mymessage():
    tkMessageBox.showinfo(title="Alert", message="Hello World!")

buttonLoop = Button(root, text="Start Loop", command=myloop)
buttonLoop.place(x=5, y=15)

buttonMessage = Button(root, text="Start Loop", command=mymessage)
buttonMessage.place(x=85, y=15)


root.mainloop()

(respuesta original a continuación)

usa un hilo

from Tkinter import *
import tkMessageBox
import threading
import time
root = Tk()
root.geometry("450x250+300+300")
root.title("Raspberry PI Test")
print dir(root)
def myloop():
    def run():
        count = 0
        while (count < 500) and root.wm_state():
           print 'The count is:', count
           count = count + 1
           time.sleep(1)

        root.after(1,count_complete)
    thread = threading.Thread(target=run)
    thread.start()
def count_complete():
    print "DONE COUNTING!! ... I am now back in the main thread"
def mymessage():
    tkMessageBox.showinfo(title="Alert", message="Hello World!")

buttonLoop = Button(root, text="Start Loop", command=myloop)
buttonLoop.place(x=5, y=15)

buttonMessage = Button(root, text="Start Loop", command=mymessage)
buttonMessage.place(x=85, y=15)


root.mainloop()

tenga en cuenta que cuando muestra el cuadro de información que se bloqueará en el nivel de API de Windows, el recuento de subprocesos esperará hasta que se cierre... para evitarlo, puede simplemente reemplazar el subprocesamiento con multiprocesamiento, creo.

Joran Beasley avatar Feb 20 '2015 22:02 Joran Beasley