Tk – GUI Composition with Classes

Since Python’s Tk widgets are classes, it is really easy to compose GUIs by using Pythons OOP capabilities. OOP works really well because we can break complex GUIs down into smaller components and then compose a larger GUI out of these components. Let’s begin with a text area control.

from tkinter import *


class TextArea(Text):
    def __init__(self, parent=None):
        Text.__init__(self, parent, width=40, height=10, border=2)
        self.pack(expand=YES, fill=BOTH, side=TOP)

if __name__ == '__main__':
    TextArea(Toplevel())
    mainloop()

This code subclasses the Text control and initializes it to what would be a reasonably sized text area control that grows and shrinks with the window. We can verify if our control is working properly by using the self-test code found in the script. Here is a screenshot of what it looks like.

textarea

It’s not much of a window, but we aren’t done composing our GUI yet either. Now let’s make some buttons that will let us load, save, and quit the application. The buttons will be arranged horizontally from left to right. This time, we are going to subclass the Frame class.

class ControlPanel(Frame):
    def __init__(self, parent=None, save=None, load=None, quit_command=exit):
        Frame.__init__(self, parent)
        Button(self, text='Save', command=save).pack(side=LEFT)
        Button(self, text='Load', command=load).pack(side=LEFT)
        Button(self, text='Exit', command=quit_command).pack(side=LEFT)
        self.pack(expand=YES, fill=BOTH, side=TOP)

if __name__ == '__main__':
    ControlPanel(Toplevel())
    mainloop()

In this example, we are using the self variable as a parent object to our 3 objects. The ControlPanel’s constructor accepts three references to functions that act as event handlers for the buttons. Inside of the constructor, we create three buttons and set their text and command attributes. Then we pack them to the left side of the layout. Finally, the frame itself is packed. Running the self-test code gives us the following window.

control_panel

The final task is to combine our controls into a single window. Once again, we are going to subclass Frame.

class TextPanel(Frame):
    def __init__(self, parent=None):
        Frame.__init__(self, parent)
        TextArea(self)
        ControlPanel(self)
        self.pack(expand=YES, fill=BOTH)

if __name__ == '__main__':
    TextPanel(Toplevel())
    mainloop()

Notice how the TextPanel class simply uses TextArea and ControlPanel. Once again, we are using composition to build up a complex GUI. The beauty of this pattern is that we can use both TextArea and ControlPanel in other GUIs. Futhermore, the TextPanel class can also get embedded into other GUIs as well.

Since all three classes have test code, we can easily see how our code is working as we develop. This is part of the reason why it’s so easy to build up GUI applications in Python using Tk or another widget toolkit. We can easily contruct GUIs using OOP and then test then instantly and independently of the application.

Here is the finished GUI followed by a complete script.

complete

from tkinter import *


class TextArea(Text):
    def __init__(self, parent=None):
        Text.__init__(self, parent, width=40, height=10, border=2)
        self.pack(expand=YES, fill=BOTH, side=TOP)


class ControlPanel(Frame):
    def __init__(self, parent=None, save=None, load=None, quit_command=exit):
        Frame.__init__(self, parent)
        Button(self, text='Save', command=save).pack(side=LEFT)
        Button(self, text='Load', command=load).pack(side=LEFT)
        Button(self, text='Exit', command=quit_command).pack(side=LEFT)
        self.pack(expand=YES, fill=BOTH, side=TOP)


class TextPanel(Frame):
    def __init__(self, parent=None):
        Frame.__init__(self, parent)
        TextArea(self)
        ControlPanel(self)
        self.pack(expand=YES, fill=BOTH)


if __name__ == '__main__':
    TextArea(Toplevel())
    ControlPanel(Toplevel())
    TextPanel(Toplevel())
    mainloop()
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s