On 26 April 2015 at 04:23, Spencer For Friends <smar...@gmail.com> wrote:
> Hi all. I'm new to Python and I'm trying my best to learn, but I'm really
> struggling with some problems.
>
> I'm using a tkinter window with a button on it to open another Python
> script. When the button is clicked and the new script loads it opens up
> it's own window over top of my tkinter window. The problem is, when I
> switch back to my tkinter window, none of the buttons are click-able
> anymore. The whole windows is unresponsive. The click animation on the
> button doesn't even function. Any help to resolve this would be greatly
> appreciated. Here is my code.

Hi Spencer,

The problem is that you're trying to run a long running task within
your applications event loop. You have to understand that the main
loop in a GUI program looks something like this:

while True:
    event = get_event_from_queue()
    if event == button_pressed:
        call_button_callback()
    elif event == key_pressed:
        respond_to_keypress()
    elif event == close_button_clicked:
        close_windows()
        break
   # etc.

Your callback function takes a long time to run and during that time
the event loop is still waiting for call_button_callback() to finish.
The result is that it doesn't respond to anything during that time.

You can test the same effect with a simpler program:

from Tkinter import Tk, Button, S
from tkMessageBox import showinfo

def callback():
    total = sum(1 for _ in xrange(10**8)) # <-- slow
    showinfo(str(total))

root = Tk()

button1 = Button(text='Click me', command=callback)
button1.config(height=3, width=25)
button1.grid(row=1, column=0, sticky=S)

root.mainloop()

When you run this program and click the button it will freeze for 5-10
seconds while running the slow callback() function. If you click
something during this time then your click will go into the event
queue. The event loop will retrieve that click message once it has
finished waiting for the callback function to finish. You can test
this by clicking the 'Click me' button and then clicking the close
button before it has finished. As soon as the callback finishes the
program will close.

The solution to this is to use threads or subprocesses. On the face of
it this is quite simple but actually writing multi-threaded code is
quite tricky. Here's how to modify the above program to run the slow
callback function in a thread:

from Tkinter import Tk, Button, S
from tkMessageBox import showinfo
from threading import Thread

def callback_threaded():
    Thread(target=callback).start()

def callback():
    total = sum(1 for _ in xrange(10**8)) # <-- slow
    showinfo(str(total))

root = Tk()

button1 = Button(text='Click me', command=callback_threaded)
button1.config(height=3, width=25)
button1.grid(row=1, column=0, sticky=S)

root.mainloop()

This program will create a separate execution thread to run the
callback. It's quite simple if you just want to run execfile in
parallel with your GUI. Where it gets trickier is if you need the
threads to interact and you need to pass data between them.


--
Oscar
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to