wxPython: How to Edit Your GUI Interactively Using reload()

Today, I came across an interesting question on StackOverflow where the author was asking how he could write a wxPython program dynamically. In other words, he wanted to be able to edit the code and basically refresh the application without closing and re-running his code. The simplest way would be to use Python's built-in reload functionality. If we go this route, then we'll need to build a little front-end to import the code that we want to change interactively.

Creating the Reloading App

wxreloader

Creating the reloading application is very straight-forward. Let's take a look at the code!

import testApp
import wx

########################################################################
class ReloaderPanel(wx.Panel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)
        self.testFrame = None
        
        showAppBtn = wx.Button(self, label="Show App")
        showAppBtn.Bind(wx.EVT_BUTTON, self.onShowApp)
        
        reloadBtn = wx.Button(self, label="Reload")
        reloadBtn.Bind(wx.EVT_BUTTON, self.onReload)
        
        mainSizer = wx.BoxSizer(wx.VERTICAL)
        mainSizer.Add(showAppBtn, 0, wx.ALL|wx.CENTER, 5)
        mainSizer.Add(reloadBtn, 0, wx.ALL|wx.CENTER, 5)
        self.SetSizer(mainSizer)
    
    #----------------------------------------------------------------------
    def onReload(self, event):
        """
        Reload the code!
        """
        if self.testFrame:
            self.testFrame.Close()
            reload(testApp)
            self.showApp()
        else:
            self.testFrame = None
        
    #----------------------------------------------------------------------
    def onShowApp(self, event):
        """
        Call the showApp() method
        """
        self.showApp()
        
    #----------------------------------------------------------------------
    def showApp(self):
        """
        Show the application we want to edit dynamically
        """
        self.testFrame = testApp.TestFrame()
        
########################################################################
class ReloaderFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Reloader")
        panel = ReloaderPanel(self)
        self.Show()
    
if __name__ == "__main__":
    app = wx.App(False)
    frame = ReloaderFrame()
    app.MainLoop()

Here we import the module that we're planning to edit while this script is running. In this case, the module is called testApp (and the file is testApp.py). Next we add a couple of buttons; one to show the testApp's frame and the other to reload the testApp code and re-show it with any changes made. Yes, we should probably add some exception handling here in case we make a typo in the code and then try to reload it, but I'll leave that as an exercise for the reader. Now we need to create the testApp.py file. Here's a simple script you can use for that:

import wx

########################################################################
class TestPanel(wx.Panel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)
        
########################################################################
class TestFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Test program")
        panel = TestPanel(self)
        self.Show()
    
if __name__ == "__main__":
    app = wx.App(False)
    frame = TestFrame()
    app.MainLoop()

Now all you have to do is edit this second file and reload it with the first file to see the changes. I recommend adding a button in the TestPanel class, saving it and then hitting the Reload button in the other script to see the changes.

Yes, it's that simple. Have fun!

Copyright © 2022 Mouse Vs Python | Powered by Pythonlibrary