Search code examples
pythonwxpython

What is the correct way to link a button to open an other py file?


I have a big doubt because my script is not performing as it should be. So I have a simple main file with a button that opens a blank grid (codes below). The problem with this code is that it opens reportWindow the first time it executes, but if I close the report and I try to open it again I receive the error : NameError: name 'TestFrame' is not defined

I've also removed if __name__ == '__main__' from the last lines of reportWindow.py because the script wasn't working with it. I tried if __name__ == 'main' as it's imported from main.py but it didn't work either.

Please, can someone show me how it should have been done the correct way?

Thank you

main.py

import wx

class Test(wx.Frame):
    def __init__(self,parent,id):
        wx.Frame.__init__(self,parent,id, "Frame aka Window", size=(300, 200))
        panel = wx.Panel(self)
        button = wx.Button(panel, label = "Exit", pos=(80, 80), size = (120,30))
        self.Bind(wx.EVT_BUTTON, self.closebutton, button)

    def closebutton(self,event):
        from reportWindow import SimpleGrid
        SimpleGrid(TestFrame, -1)

if __name__ == '__main__':
    app = wx.App()  
    frame = Test(parent=None, id=1)
    frame.Show()
    app.MainLoop()

reportWindow.py

import wx
import wx.grid as gridlib

class SimpleGrid(gridlib.Grid): ##, mixins.GridAutoEditMixin):
    def __init__(self, parent, log):
        gridlib.Grid.__init__(self, parent, -1)

        #[...Some code...]


class TestFrame(wx.Frame):
    def __init__(self, parent, log):
        wx.Frame.__init__(self, parent, 0, "Title", size=(1400,800))
        self.grid = SimpleGrid(self, log)

        #[...Some code...]


#if __name__ == '__main__':
import sys
from wx.lib.mixins.inspection import InspectableApp
app = InspectableApp(False)
frame = TestFrame(None, sys.stdout)
frame.Show(True)
#import wx.lib.inspection
#wx.lib.inspection.InspectionTool().Show()
app.MainLoop()

Solution

  • Your code has a few of issues.

    1) The NameError is occurring because you're not importing TestFrame from reportWindow.

    2) Without if __name__ == "__main__" in reportWindow.py your program will create another wx.App and start another MainLoop which will block the first loop from receiving events etc... You should only create 1 App/MainLoop. It will also create the TestFrame the first time you import reportWindow.

    3) It looks like you want SimpleGrid to be a child of TestFrame, but then you try to create it by itself in closebutton.

    4) When creating the SimpleGrid you pass the TestFrame class instead of an instance of the TestFrame class.

    Here is the modified code

    # main.py
    import wx, sys
    
    
    class Test(wx.Frame):
        def __init__(self, parent, id):
            wx.Frame.__init__(self, parent, id, "Frame aka Window", size=(300, 200))
            panel = wx.Panel(self)
            button = wx.Button(panel, label="Exit", pos=(80, 80), size=(120, 30))
            self.Bind(wx.EVT_BUTTON, self.closebutton, button)
    
        def closebutton(self, event):
            from reportWindow import TestFrame
    
            frame = TestFrame(self, sys.stdout)
            frame.Show()
    
    
    if __name__ == '__main__':
        app = wx.App()
        frame = Test(parent=None, id=1)
        frame.Show()
        app.MainLoop()
    

    # reportWindow.py
    import wx
    import wx.grid as gridlib
    
    
    class SimpleGrid(gridlib.Grid):  ##, mixins.GridAutoEditMixin):
        def __init__(self, parent, log):
            gridlib.Grid.__init__(self, parent, -1)
    
            # [...Some code...]
    
    
    class TestFrame(wx.Frame):
        def __init__(self, parent, log):
            wx.Frame.__init__(self, parent, 0, "Title", size=(1400, 800))
            self.grid = SimpleGrid(self, log)
    
            # [...Some code...]
    
    
    if __name__ == '__main__':
        import sys
        from wx.lib.mixins.inspection import InspectableApp
    
        app = InspectableApp(False)
        frame = TestFrame(None, sys.stdout)
        frame.Show(True)
        import wx.lib.inspection
        wx.lib.inspection.InspectionTool().Show()
        app.MainLoop()