Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interacting with Tkinter window during a long process

I have a basic python class that creates a window using the standard Tkinter library:

import Tkinter

class GUI(Tkinter.Tk):

    def __init__(self,parent):
        Tkinter.Tk.__init__(self,parent)
        self.parent = parent
        self.initialize()

    def lock_func(self):
        while 1==1:
            print "blah"

    def initialize(self):
        self.processBtn = Tkinter.Button(self, text="Process", command=self.lock_func)
        self.processBtn.pack()        

app = GUI(None)
app.mainloop()

when I hit the Process button, the window doesn't respond. I want to be able to close the program (using the x button) whene the lock_func is runing.

like image 622
Ghilas BELHADJ Avatar asked Aug 04 '13 00:08

Ghilas BELHADJ


1 Answers

You could use a generator to hold the state within the loop, and use yield to relinquish control back to the main loop. Then use self.after to repeatedly call the generator's next method to simulate the effect of while True -- but doing it in a way which is friendly to Tkinter's main loop.

import Tkinter as tk

class App(object):
    def __init__(self, master):
        self.master = master
        self.initialize()

    def lock_func(self):
        def step():
            while True:
                print("blah")
                self.nextstep_id = self.master.after(1, nextstep)
                yield
        nextstep = step().next
        self.nextstep_id = self.master.after(1, nextstep)

    def stop(self):
        self.master.after_cancel(self.nextstep_id)
        print("stopped")

    def initialize(self):
        self.nextstep_id = 0
        self.process_button = tk.Button(self.master, text="Process",
                                        command=self.lock_func)
        self.stop_button = tk.Button(self.master, text="Stop",
                                     command=self.stop)        
        self.process_button.pack()
        self.stop_button.pack(expand='yes', fill='x')

root = tk.Tk()
app = App(root)
root.mainloop()
like image 162
unutbu Avatar answered Oct 20 '22 11:10

unutbu