[Tkinter-discuss] single button threading
Cameron Laird
Cameron at phaseit.net
Tue Jun 19 21:27:51 CEST 2007
On Mon, Jun 18, 2007 at 10:50:13AM +0200, Michael Lange wrote:
.
.
.
> Brill IanT <woswwf at yahoo.co.uk> wrote:
>
> > I am writing an application which fetches and parses a large number of urls for hyperlinks.
> >
> > My problem is that when the prog is in the middle of the 'fetching' stage, the gui becomes almost completely unresponsive.
> >
> > This is not at all what I want. I want the user to be able to interact with the gui while this process is going on. Even if just one button, a 'stop' button, is the only thing working, I would be satisfied with that.
> >
> > Is there a way to perhaps thread a button or two while urllib2 is busy fetching a big list of urls? I ask this with some trepidation because I know how thread unfriendly tkinter is.
> >
>
> I did not find it that hard to use Tkinter with threads. You just have to make sure that
> all interaction with Tk is done from the main (gui) thread. Typically I use a bunch
> of variables to handle communication between Tkinter and the child thread, so the
> "Stop" button would set a "stop_child_thread" flag to True, whereas the child
> thread continually updates a "progress" flag that allows the gui to draw some visual feedback
> about the progress made by the child.
>
> I hope this helps
.
.
.
There certainly are people who regard Tkinter threading as touchy.
I choose not to argue that point today.
I *will* point out that, in essentially all common systems (not
just Tkinter, and not just any particular operating system), you'll
need to confine your GUI work to a single thread.
Let's sidestep all that for right now, and look at an example of a
responsive urllib2-using GUI in a single thread:
from Tkinter import *
from urllib2 import *
master = Tk()
def fetch_action():
l.configure(text = "Beginning download")
l.after(0, download)
def download():
global total_read
global stop_reading
URL = "http://wiki.python.org/moin/RecentChanges"
f = urlopen(URL)
total_read = 0
stop_reading = 0
l.after(0, read_more, f, 100)
def read_more(handle, octets):
global total_read
global stop_reading
if stop_reading:
return
print handle.read(octets),
total_read += octets
l.configure(text = "%d octets read" % total_read)
l.after(1, read_more, handle, octets)
def stop():
global stop_reading
stop_reading = 1
l = Label(master, text = 40 * " ")
b1 = Button(master, text = "Fetch", command = fetch_action)
b2 = Button(master, text = "Stop reading", command = stop)
l.pack()
b1.pack()
b2.pack()
mainloop()
I like to think this speaks for itself. If you execute this application
for itself, you'll see a GUI that remains responsive even while urllib2
operations are proceeding.
More information about the Tkinter-discuss
mailing list