Pages

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:

  1. 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

    ReplyDelete
  2. 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

    ReplyDelete
  3. 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.

    ReplyDelete