Dave Reed <[EMAIL PROTECTED]> writes:

> There have been a number of questions on this list about using
> Glade/pygtk together. I have written some software that produces a
> skeleton of your program's code with empty callbacks/signal handlers
> based on the contents of the glade XML file.

Thanks for making your code available.  It would be interesting to
hear how others in this group organize their pygtk and Glade code.  I
don't know if anyone else will care to share their ideas.  I have a
few thoughts about connecting signal handlers using libglade and
pygtk -- I hope it isn't too dry and boring.

There are at least 3 ways to connect signal handlers to pygtk libglade
widgets: code generation, libglade autoconnect and introspection.

Code generation has advantages, but also a few disadvantages too.  I
think the biggest practical problem is that it can be hard to keep the
code in sync with changes to the Glade file.  First, you have to
remember to regenerate the skeleton when you change the Glade file.
That's not too bad, but a bigger problem is that it can be hard to
merge the code you used to fill out an old skeleton into a newly
generated skeleton.  In order to avoid overwriting too much
hand-written code and to make merging easier, it is sometimes
suggested to divide the interface into several small Glade files so
that each generated skeleton is smaller.  Code generation of skeletons
can make it easier to get started but I think it makes updates
significantly harder.  I prefer code generation techniques when they
can create complete functions or classes rather than skeletons so that
the update problem is minimized.  (If changes to the generated code
are rare then skeletons can be fine but this isn't my experience with
what happens with typical GUI view and controller code.)

Questions about libglade autoconnect come up on this list fairly
regularly.  Autoconnect is probably a good approach for libglade
projects in C, but I'm not a fan of using it with pygtk.  Glade should
be used to build the view.  Signal handlers are part of the controller
so I don't think they belong in the Glade file.  Glade needs the
signal and handler names to direct its code generation, but with
libglade we can make a cleaner separation between view and controller
so we shouldn't have to specify the signal handlers in two places.
One thing I do like about the Glade signal dialog is that it does a
good job of showing the signals that are available for each widget.

Introspection allows you to specify the signal handlers in a natural
way in your pygtk code and have them connected automatically.  This is
one of several ideas that Christian Reis uses to great effect in Kiwi.
Controller classes automatically connect signals based on method names
that match patterns like on_widget__signal and after_widget__signal.
There is no need to specify the signal handlers in Glade since this
information is not used.  To connect to another widget or signal you
just write a new method with the appropriate name and no changes are
needed to the Glade file.  Of course this constrains signal handler
method names to fit the chosen patterns, but I think this is a good
coding practice anyway.  This is the approach I like best.

The pygtk FAQ entry 22.1 talks about connecting signals when using
libglade.  It includes some links and some example code.  One example
given uses introspection + autoconnect.  I don't understand this
choice since it needlessly brings with it all the disadvantages of
libglade autoconnect.  Instead, something like this seems better since
all signal handling stuff remains in the Python code and there is no
need to set signals and handler names in the Glade file:

    import re
    # Regular expression to match handler method names patterns
    # on_widget__signal and after_widget__signal.  Note that we use two
    # underscores between the Glade widget name and the signal name.
    handler_re = re.compile(r'^(on|after)_(.*)__(.*)$')

    class GladeWidget:
        def init(self, glade_file, widget_name):
            """Connects signal handling methods to Glade widgets.

            Methods named like on_widget__signal or after_widget__signal
            are connected to the appropriate widgets and signals.
            """
            get_widget = gtk.glade.XML(glade_file, widget_name).get_widget
            for attr in dir(self):
                match = handler_re.match(attr)
                if match:
                    when, widget, signal = match.groups()
                    method = getattr(self, attr)
                    assert callable(method)
                    if when == 'on':
                        get_widget(widget).connect(signal, method)
                    elif when == 'after':
                        get_widget(widget).connect_after(signal, method)
                elif attr.startswith('on_') or attr.startswith('after_'):
                    # Warn about some possible typos like separating
                    # widget and signal name with _ instead of __.
                    print ('Warning: attribute %r not connected'
                           ' as a signal handler' % (attr,))
_______________________________________________
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/

Reply via email to