Examining the PyGtk Toolkit
by Mitch Chapman and Brian Kelley 


Example 1:  

class GtkModalDialog:
    def runModal(self):
        self.window.show()
        gtk.mainloop()
    def endModal(self):
        self.window.hide()
        gtk.mainquit()


Listing One
#!/usr/bin/env python
"""AppWindow.py:
This module provides an application window --
a GtkWindow that knows when to quit."""
import gtk
class AppWindow(gtk.GtkWindow):
    """This is just a GtkWindow which exits its event loop when destroyed."""
    def __init__(self, title=None):
        """Initialize a new instance.
        If specified, `title' will be displayed in the window's title bar."""
        gtk.GtkWindow.__init__(self)
        if title:
            self.set_title(title)
        self.connect("delete_event", self.quit)
    def quit(self, *args):
        """Exit the application -- or at least exit its event loop."""
        gtk.mainquit()
def main():
    """Module mainline (for standalone execution)"""
    win = AppWindow(title="Sample App Window")
    label = gtk.GtkLabel("Hello, world.")
    win.add(label)
    label.show()
    win.show()
    gtk.mainloop()
if __name__ == "__main__":
    main()

Listing Two
#!/usr/bin/env python
"""This module demonstates techniques for aligning labels in a form."""

import gtk
import AppWindow
class UI:
    """Builds a form consisting of several rows of labelled entries."""
    def __init__(self):
        """Initialize a new instance."""
        self.top = AppWindow.AppWindow(title="Alignment Demo")
        self.box = gtk.GtkVBox()
        self.top.add(self.box)
        self.box.show()
        self.table = gtk.GtkTable(cols=2)
        self.box.pack_start(self.table)
        self.table.show()
        self.addBtn = gtk.GtkButton("Add Row")
        self.addBtn.connect("clicked", self.addBtnCB)
        self.box.pack_end(self.addBtn, fill=gtk.FALSE, expand=gtk.FALSE)
        self.addBtn.show()

        # Keep a list of the entries added.
        self.entry = []
    def mainloop(self):
        """Show the window and run the main event loop."""
        
        # If you don't check_size() on the containing window after setting the
        # border width, you may get a nasty surprise: a minimally-sized window.
        # Work around the problem by setting the border width,
        # spacing, etc. _after_ creating all of the tablel content and
        # _before_ showing the containing window.
        self.table.set_border_width(5)
        self.table.set_col_spacings(5)
        self.table.set_row_spacings(5)
        self.top.show()
        gtk.mainloop()
    def addEntry(self, label):
        """Add a new labelled entry.
        `label' specifies the label to be displayed."""
        # Add each new entry to the next available row.
        row = len(self.entry)
        
        l = gtk.GtkLabel(label + ":")
        l.set_alignment(1.0, 0.5)
        self.table.attach(l, 0, 1, row, row + 1)
        l.show()
        e = gtk.GtkEntry()
        self.table.attach(e, 1, 2, row, row + 1)
        e.show()
        self.entry.append(e)
        return e
    def addBtnCB(self, *args):
        """Callback invoked when the Add button is clicked."""
        self.addEntry("Row %d" % len(self.entry))
def main():
    """Module mainline (for standalone execution)"""
    ui = UI()
    for label in ["Name", "Quest", "Favorite Color"]:
        ui.addEntry(label)
    ui.mainloop()
if __name__ == "__main__":
    main()

Listing Three
#!/usr/bin/env python
"""This module shows ways of aligning labels in a form -- and also how
to maintain spacing for dynamically-added labels."""

import gtk
import AppWindow

class UI:
    """Builds a form consisting of several rows of labelled entries."""
    def __init__(self):
        """Initialize a new instance."""
        self.top = AppWindow.AppWindow(title="Alignment Demo")
        self.box = gtk.GtkVBox()
        self.top.add(self.box)
        self.box.show()
        self.table = gtk.GtkTable(cols=2)
        self.box.pack_start(self.table)
        self.table.show()
        self.addBtn = gtk.GtkButton("Add Row")
        self.addBtn.connect("clicked", self.addBtnCB)
        self.box.pack_end(self.addBtn, fill=gtk.FALSE, expand=gtk.FALSE)
        self.addBtn.show()

        # Keep a list of the entries added.
        self.entry = []
    def mainloop(self):
        """Show the window and run the main event loop."""
        # If you don't check_size() on the containing window after setting the
        # border width, you may get a nasty surprise: a minimally-sized window.
        # Work around the problem by setting the border width,
        # spacing, etc. _after_ creating all of the tablel content and
        # _before_ showing the containing window.
        self.table.set_border_width(5)
        self.table.set_col_spacings(5)
        self.table.set_row_spacings(5)
        
        self.top.show()
        gtk.mainloop()
    def addEntry(self, label):
        """Add a new labelled entry.
        `label' specifies the label to be displayed."""
        # Each new entry is added to the next available row.
        row = len(self.entry)
        
        l = gtk.GtkLabel(label + ":")
        l.set_alignment(1.0, 0.5)
        self.table.attach(l, 0, 1, row, row + 1)
        l.show()
        
        e = gtk.GtkEntry()
        self.table.attach(e, 1, 2, row, row + 1)
        e.show()

        self.entry.append(e)
        # set_row_spacings() affects only the rows of which the
        # table is already aware, or so it seems.
        # To work around this, set the spacing for each row as it is added.
        if row > 0:
            self.table.set_row_spacing(row - 1, 5)
        return e
    def addBtnCB(self, *args):
        """Callback invoked when the Add button is clicked."""
        self.addEntry("Row %d" % len(self.entry))
def main():
    """Module mainline (for standalone execution)"""
    ui = UI()
    for label in ["Name", "Quest", "Favorite Color"]:
        ui.addEntry(label)
    ui.mainloop()
if __name__ == "__main__":
    main()

Listing Four
#!/usr/bin/env python
"""This module shows how to adjust the limits on a GtkSpinButton, and
how to use GtkAdjustments to keep several widgets in lock step."""

import gtk, GTK, AppWindow
class UI:
    """Demonstrates how to control the limits on a spinbutton."""
    def __init__(self, upperBound=10):
        """Initialize a new instance."""
        self.top = AppWindow.AppWindow(title="Spinbutton Limits")
        self.table = gtk.GtkTable()
        self.top.add(self.table)
        self.table.show()
        self.spinBtn = gtk.GtkSpinButton()
        self.spinBtn.connect("activate", self.spinEntryActivateCB)
        self.table.attach(self.spinBtn, 0, 1, 0, 1)
        self.spinBtn.show()
        self.scrollbar = gtk.GtkHScrollbar()
        self.scrollbar['width'] = 200
        self.table.attach(self.scrollbar, 0, 1, 1, 2)
        self.scrollbar.show()
        self.scale = gtk.GtkHScale()
        self.table.attach(self.scale, 0, 1, 2, 3)
        self.scale.show()
        self.setUpperBound(upperBound)
    def mainloop(self):
        """Show the application window and run the main event loop."""
        self.top.show()
        gtk.mainloop()
    def spinEntryActivateCB(self, *args):
        """Callback invoked when the user enters a new value in the
        spinbutton entry field."""
        # Use get_text() and convert the value to a number; get_value() clips 
        # the value to the current spinbutton bounds before returning it.
        self.setUpperBound(float(self.spinBtn.get_text()))
    def setUpperBound(self, upperBound):
        """Set a new upper bound for the spinbutton, scrollbar et al."""
        # Ignore any upper bounds which are less than the current
        # lower bound. (Default lower bound for a spinbutton is zero.)
        if upperBound <= 0:
            return
        # Apply the new upper bound, but keep all other adjustments
        # at their current value.

        # Can't use self.spinBtn.get_adjustment(), because it references
        # a non-existent attribute ('sel' should be 'self').
        o = self.spinBtn._o
        adj = gtk._obj2inst(gtk._gtk.gtk_spin_button_get_adjustment(o))

        # Create a new GtkAdjustment and tell spinbutton, etc, to use it.
        newAdj = gtk.GtkAdjustment(adj.value, adj.lower, upperBound,
                     max(1, adj.step_increment), max(1, adj.page_increment),
                     max(1, adj.page_size))
        self.spinBtn.set_adjustment(newAdj)
        self.scrollbar.set_adjustment(newAdj)
        self.scale.set_adjustment(newAdj)
def main():
    """Module mainline (for standalone execution)"""
    ui = UI()
    ui.mainloop()
if __name__ == "__main__":
    main()







1


