December 8, 2009

Python 3 - tkinter ttk (Tk Themed Widgets) - Blocking Command Example

Here is another example GUI application with ttk in Python 3.1.

This example shows usage of the Button, Text, and Scrollbar widgets, along with some basic layout management using grid().

To use it, enter a URL and click the button. It will send an HTTP GET request to the URL and insert the response headers into the Text widget. You will notice that the GUI is blocked (frozen) while the URL is fetched. This is because all of the work is done in the main event thread. I will show how to use threads for non-blocking events in a future post.

It renders on Ubuntu (with Gnome) like this:

Code:

#!/usr/bin/env python
# Python 3


import tkinter
from tkinter import ttk
import urllib.request



class Application:
    def __init__(self, root):
        self.root = root
        self.root.title('Blocking Command Demo')
        
        self.init_widgets()
            
            
    def init_widgets(self):
        self.btn = ttk.Button(self.root, command=self.get_url, text='Get Url', width=8)
        self.btn.grid(column=0, row=0, sticky='w')
        
        self.entry = ttk.Entry(self.root, width=60)
        self.entry.grid(column=0, row=0, sticky='e')
        
        self.txt = tkinter.Text(self.root, width=80, height=20)
        self.txt.grid(column=0, row=1, sticky='nwes')
        sb = ttk.Scrollbar(command=self.txt.yview, orient='vertical')
        sb.grid(column=1, row=1, sticky='ns')
        self.txt['yscrollcommand'] = sb.set
        

    def get_url(self):
        url = self.entry.get()
        headers = urllib.request.urlopen(url).info()
        self.txt.insert(tkinter.INSERT, headers)
    
    

if __name__ == '__main__':
    root = tkinter.Tk()
    Application(root)
    root.mainloop()

3 comments:

Matt said...

I got an error:

Traceback (most recent call last):
File "/Users/Matt/Documents/tkinterex.py", line 42, in module>
Application(root)
File "/Users/Matt/Documents/tkinterex.py", line 16, in __init__
self.init_widgets()
File "/Users/Matt/Documents/tkinterex.py", line 20, in init_widgets
self.btn = ttk.Button(self.root, command=self.get_url, text='Get Url', width='8')
File "/Library/Frameworks/Python.framework/Versions/3.1/lib/python3.1/tkinter/ttk.py", line 614, in __init__
Widget.__init__(self, master, "ttk::button", kw)
File "/Library/Frameworks/Python.framework/Versions/3.1/lib/python3.1/tkinter/ttk.py", line 559, in __init__
_load_tile(master)
File "/Library/Frameworks/Python.framework/Versions/3.1/lib/python3.1/tkinter/ttk.py", line 47, in _load_tile
master.tk.eval('package require tile') # TclError may be raised here
_tkinter.TclError: can't find package tile


Any ideas?

Thanks,

Matt

Corey Goldberg said...

not sure... but it looks like you might not have Tk itself installed (just the PythonTk bindings).. can you look for a Tk package to install?

-Corey

nosklo said...

Huh? It seems like you don't need threading to make it non-blocking; There's Tkinter.tkinter.createfilehandler that can register a callback for when the request arrives - so the main loop can continue and you don't need to block.