Search code examples
user-interfacegtkpygtkreload

Create a PyGTK GUI with event to reload itself


I'm prototyping GUI layout with PyGTK, sometimes using glade/builder sometimes not, and the following scene repeats endlessly:

  1. Modify the code
  2. Run the GUI script
  3. Judge the result
  4. Modify again
  5. Run again...

So, since I heard that Python allows reloading of modules, I would like to know if it is possible to modify the code WITHOUT CLOSING THE WINDOW, and then, from the window itself, say, clicking on a button, "reload" the window reflecting the changes in code.

Since it is a conceptual question, I don't have any specific code to show.

Thanks for the attention


Solution

  • I think it is possible if you do the following:

    1. Identify and isolate the widget W that you want to see updated when you press the button (if you want to see the whole window updated, then make it whatever you add in the window, not the window itself).
    2. Write a function (or class) that creates and returns this widget
    3. Put this function or class in a module that you will reload
    4. Create your button outside W and connect it to a function that does the following
      • Remove current W from window
      • Reload the module
      • Create new instance of W
      • Add it to the window

    Of course, the critical step here is "reload the module". I guess you have to make sure no code from the module is running and no other module depends on variables defined on this module.

    EDIT: I had some time, so I made a little prototype. Change the label in widget_module.py and then hit Update

    gui.py

    # Load in pygtk and gtk
    
    import pygtk
    pygtk.require('2.0')
    import gtk
    import widget_module
    
    # Define the main window
    
    class Whc:
        def __init__(self):
            # Window and framework
            self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
            self.window.connect("destroy", self.destroy)
    
            # A Button, with an action
            # Add it to the geometry
            # show the button
            self.button = gtk.Button("Update")
            self.button.connect("clicked", self.update, None)
    
            self.vbox = gtk.VBox()
            self.vbox.pack_start(self.button)
            self.widget = widget_module.get_widget()
            self.vbox.pack_start(self.widget)
    
            self.window.add(self.vbox)
    
    
            # Show the window
            self.window.show_all()
    
        # Callback function for use when the button is pressed
    
        def update(self, widget, data=None):
            print "Update"
            self.vbox.remove(self.widget)
            reload(widget_module)
            self.widget = widget_module.get_widget()
            self.vbox.pack_start(self.widget)
            self.widget.show()
    
    
        # Destroy method causes appliaction to exit
        # when main window closed
    
        def destroy(self, widget, data=None):
            gtk.main_quit()
    
        # All PyGTK applicatons need a main method - event loop
    
        def main(self):
            gtk.main()
    
    if __name__ == "__main__":
        base = Whc()
        base.main()
    

    widget_module.py

    import pygtk
    import gtk
    
    def get_widget():
        return gtk.Label("hello")