Hello,
(First of all, I want to apologize for any bad English.)
I am developing a GTK+ app with Glade 3 and Python. I read Micah Carrick's blog entries (which helped a lot) and decided to use Gtk Builder instead of libglade.
The code consists of 4 classes:
- The App class, in which the builder object is created. It also connects the signals and shows the main window.
- The BaseWindowWrapper class, which is a base class for initializing a window.
- The MainWindowWrapper class, which is derived from BaseWindowWrapper. This is the startup window.
- The PreferencesWindowWrapper class, which is also derived from BaseWindowWrapper. This window is shown when the user clicks the Edit-Preferences menu item.
Code:
import pygtk
pygtk.require('2.0')
import gtk
class BaseWindowWrapper:
def __init__(self, builder, name):
self.builder = builder
self.window = self.builder.get_object(name)
class PreferencesWindowWrapper(BaseWindowWrapper):
def __init__(self, builder, name):
BaseWindowWrapper.__init__(self, builder, name)
self.window.connect("delete-event", self.delete_event, self)
def delete_event(self, dialog, event, app):
self.window.hide()
return True
def on_buttonClose_clicked(self, widget, data=None):
self.window.hide()
class MainWindowWrapper(BaseWindowWrapper):
def __init__(self, builder, name):
BaseWindowWrapper.__init__(self, builder, name)
self.preferencesWindow = PreferencesWindowWrapper(builder, "PreferencesWindow")
def on_menuEditPreferences_activate(self, widget, data=None):
self.preferencesWindow.window.show()
def on_MainWindow_destroy(self, widget, data=None):
gtk.main_quit()
class App:
def __init__(self):
self.builder = gtk.Builder()
self.builder.add_from_file("ui.ui")
self.mainWindow = MainWindowWrapper(self.builder, "MainWindow")
signals = { "on_menuEditPreferences_activate": self.mainWindow.on_menuEditPreferences_activate,
"on_MainWindow_destroy" : self.mainWindow.on_MainWindow_destroy,
"on_buttonClose_clicked": self.mainWindow.preferencesWindow.on_buttonClose_clicked }
self.builder.connect_signals(signals)
# Run main application window
def main(self):
self.mainWindow.window.show()
gtk.main()
if __name__ == "__main__":
app = App()
app.main()
The code works, but I think it is rather complicated. The thing that disturbs me most is the connect_signals line. I would like to put it into the two window classes like this (lines 5 and 18):Code:
class PreferencesWindowWrapper(BaseWindowWrapper):
def __init__(self, builder, name):
BaseWindowWrapper.__init__(self, builder, name)
self.builder.connect_signals(self) # This should connect the on_buttonClose_clicked method
self.window.connect("delete-event", self.delete_event, self)
def delete_event(self, dialog, event, app):
self.window.hide()
return True
def on_buttonClose_clicked(self, widget, data=None):
self.window.hide()
class MainWindowWrapper(BaseWindowWrapper):
def __init__(self, builder, name):
BaseWindowWrapper.__init__(self, builder, name)
self.builder.connect_signals(self) # This should connect the on_menuEditPreferences_activate method and all other methods, which connect_signals finds in this class
self.preferencesWindow = PreferencesWindowWrapper(builder, "PreferencesWindow")
Doing it this way, only the signals of the MainWindow class are connected. The on_buttonClose_clicked method of the PreferencesWindow class is never executed, although I specified self.builder.connect_signals(self) (line 5). If I put the on_buttonClose_clicked method into the MainWindow class everything works fine, but then I do not have to create an extra class...
So it seems that the connecting is only done once. Or am I'm doing something completely wrong? Should I rather use libglade?
Thanks in advance for looking through this and best regards,
benny
The glade file:
Code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.4.5 on Mon Jul 14 15:30:38 2008 -->
<glade-interface>
<widget class="GtkWindow" id="MainWindow">
<signal name="destroy" handler="on_MainWindow_destroy"/>
<child>
<widget class="GtkVBox" id="vbox2">
<property name="visible">True</property>
<child>
<widget class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
<child>
<widget class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="label" translatable="yes">_Datei</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menu1">
<property name="visible">True</property>
<child>
<widget class="GtkImageMenuItem" id="imagemenuitem1">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-new</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="imagemenuitem2">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-open</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="imagemenuitem3">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-save</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="imagemenuitem4">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-save-as</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="imagemenuitem5">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-quit</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="menuitem2">
<property name="visible">True</property>
<property name="label" translatable="yes">_Bearbeiten</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menu2">
<property name="visible">True</property>
<child>
<widget class="GtkImageMenuItem" id="imagemenuitem6">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-cut</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="imagemenuitem7">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-copy</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="imagemenuitem8">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-paste</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="imagemenuitem9">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-delete</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-preferences</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_menuEditPreferences_activate"/>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="menuitem3">
<property name="visible">True</property>
<property name="label" translatable="yes">_Ansicht</property>
<property name="use_underline">True</property>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="menuitem4">
<property name="visible">True</property>
<property name="label" translatable="yes">_Hilfe</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menu3">
<property name="visible">True</property>
<child>
<widget class="GtkImageMenuItem" id="imagemenuitem10">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-about</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</widget>
</child>
</widget>
<widget class="GtkWindow" id="PreferencesWindow">
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<child>
<placeholder/>
</child>
<child>
<widget class="GtkButton" id="button1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="border_width">10</property>
<property name="label" translatable="yes">gtk-close</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
<signal name="clicked" handler="on_buttonClose_clicked"/>
</widget>
<packing>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>