5

I'm working on a fairly large GUI project and am thus using wxpython to build it. I have one frame, multiple frames with their own functions and a main file that imports the gui components as well as other, external functions. I've decided to keep the gui/wxpython code different to better modularize the code.

The main question I have is how to execute the functions in the separate panels and how to make them work from my main python file.

Below is a sample of my wxpython code:

import wx

class MainFrame ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 800,600 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

        bSizer1 = wx.BoxSizer( wx.VERTICAL )

        self.SetSizer( bSizer1 )
        self.Layout()

        self.panelOne = panel_one(self)
        self.panelTwo = panel_two(self)

        self.panelTwo.Hide()


        self.Centre( wx.BOTH )

    def __del__( self ):
        pass


class panel_one ( wx.Panel ):

    def __init__( self, parent ):
        wx.Panel.__init__ ( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.Size( 800,600 ), style = wx.TAB_TRAVERSAL )

        bSizer5 = wx.BoxSizer( wx.VERTICAL )

        self.m_button2 = wx.Button( self, wx.ID_ANY, u"MyButton", wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer5.Add( self.m_button2, 0, wx.ALL, 5 )

        self.SetSizer( bSizer5 )
        self.Layout()

        # Connect Events
        self.m_button2.Bind( wx.EVT_BUTTON, self.changeIntroPanel )

    def __del__( self ):
        pass


    # Virtual event handlers, overide them in your derived class
    def changeIntroPanel( self, event ):
        event.Skip()



class panel_two ( wx.Panel ):


    def __init__( self, parent ):
        wx.Panel.__init__ ( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.Size( 800,600 ), style = wx.TAB_TRAVERSAL )

    ... some code in here ...

    def __del__( self ):
    pass

So those are my gui components. Then, in my main file, I import it and run the gui:

import gui

class MainApp(gui.MainFrame):
    def __init__(self, parent):
        gui.MainFrame.__init__(self, parent)

        self.panelOne = Panel1(self)
        self.panelTwo = Panel2(self)
        self.panelTwo.Hide()

class Panel1(gui.panel_one):
    def __init__(self, parent):
        gui.panel_one.__init__(self, parent)

    def changeIntroPanel( self, event ):
            if self.panelOne.IsShown():
                self.SetTitle("Panel Two Showing")
                self.PanelOne.Hide()
                self.PanelTwo.Show()
            else:
                self.SetTitle("Panel One Showing")
                self.PanelOne.Show()
                self.PanelTwo.Hide()
            self.Layout()


class Panel2(gui.panel_two):
    def __init__(self, parent):
        gui.panel_two.__init__(self, parent)

def main():
    app = wx.App()
    window = MainApp(None)
    window.Show(True)
    app.MainLoop()

if __name__ == '__main__':
    main()

As you can tell, the idea is that I want to do all my implementation in my main file. How would I go about defining the functionality of my changeIntroPanel function that was first defined in panel_one? For now, the idea is to hide panelOne and show panelTwo.

I have done something similar before, but only with one frame. In that case, it was trivial since all the functions are in the MainFrame class to begin with. In that case, the code I posted would work perfectly.

Any help is appreciated. Thank you.

intl
  • 2,753
  • 9
  • 45
  • 71
  • overide changeIntroPanel in your derived class. You can define class MainPanelOne ( gui.panel_one) just like your "MainApp" – Jerry_Y Feb 20 '14 at 05:58
  • Thank you for the input. I did so, as you said. My idea is to create the two panels and pass them in when I'm calling window = MainApp(None) in main(). The problem is, though, p1 and p2 are being created, I get the following exception: can't create wxWindowMac without parent. Seeing as I can create the frame with no parent, who not the panels? – intl Feb 20 '14 at 06:08
  • 1
    How about this: window = MainApp(None) p1 = Panel1(window ) p2 = Panel2(window) window.Show() – Jerry_Y Feb 20 '14 at 06:17
  • And you'd better remove the initialization for panelOne/paneltwo and put it in OnInit of your MainApp – Jerry_Y Feb 20 '14 at 06:21
  • You beat me to it, that worked. I removed the initializations from the main gui class. If I'm creating p1 and p2 in my main and then passing opening them, how would I go about adding it to MainApp's OnInit? – intl Feb 20 '14 at 06:27
  • Essentially, my question is that by creating p1 and p2 in the main class, how do I access them in the classes? – intl Feb 20 '14 at 06:30

1 Answers1

10

def OnInit(self, parent): is used for wx.App, you need def _ _init_ _(self, parent) instead.

About __init__ please check: Using inheritance in python

About difference between __init__ and OnInit please check this link

Edit:

gui.py

import wx

class MainFrame ( wx.Frame ):
    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 800,600 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
        bSizer1 = wx.BoxSizer( wx.VERTICAL )
        self.SetSizer( bSizer1 )
        self.Layout()

        # self.panelOne = panel_one(self)
        # self.panelTwo = panel_two(self)
        # self.panelTwo.Hide()
        self.Centre( wx.BOTH )
    def __del__( self ):
        pass

class panel_one ( wx.Panel ):
    def __init__( self, parent ):
        wx.Panel.__init__ ( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.Size( 800,600 ), style = wx.TAB_TRAVERSAL )
        bSizer5 = wx.BoxSizer( wx.VERTICAL )
        self.m_button2 = wx.Button( self, wx.ID_ANY, u"panel 1 button", wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer5.Add( self.m_button2, 0, wx.ALL, 5 )
        self.SetSizer( bSizer5 )
        self.Layout()
        # Connect Events
        self.m_button2.Bind( wx.EVT_BUTTON, self.changeIntroPanel )
    def __del__( self ):
        pass
    # Virtual event handlers, overide them in your derived class
    def changeIntroPanel( self, event ):
        event.Skip()

class panel_two ( wx.Panel ):
    def __init__( self, parent ):
        wx.Panel.__init__ ( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.Size( 800,600 ), style = wx.TAB_TRAVERSAL )
        bSizer5 = wx.BoxSizer( wx.VERTICAL )
        self.m_button2 = wx.Button( self, wx.ID_ANY, u"panel 2 button ", wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer5.Add( self.m_button2, 0, wx.ALL, 5 )
        self.SetSizer( bSizer5 )
        self.Layout()
        # Connect Events
        self.m_button2.Bind( wx.EVT_BUTTON, self.changeIntroPanel )

    def __del__( self ):
        pass
        # Virtual event handlers, overide them in your derived class
    def changeIntroPanel( self, event ):
        event.Skip()

mainapp.py

import wx
import gui

class MainApp(gui.MainFrame):
    def __init__(self, parent):
        gui.MainFrame.__init__(self, parent)

        self.panelOne = Panel1(self)
        self.panelTwo = Panel2(self)
        self.panelTwo.Hide()

class Panel1(gui.panel_one):
    def __init__(self, parent):
        gui.panel_one.__init__(self, parent)
        self.parent = parent

    def changeIntroPanel( self, event ):
        if self.IsShown():
            self.parent.SetTitle("Panel Two Showing")
            self.Hide()
            self.parent.panelTwo.Show()


class Panel2(gui.panel_two):
    def __init__(self, parent):
        gui.panel_two.__init__(self, parent)
        self.parent = parent

    def changeIntroPanel( self, event ):
        if self.IsShown():
            self.parent.SetTitle("Panel One Showing")
            self.parent.panelOne.Show()
            self.Hide()

def main():
    app = wx.App()
    window = MainApp(None)
    window.Show(True)
    app.MainLoop()

if __name__ == '__main__':
    main()
Community
  • 1
  • 1
Jerry_Y
  • 1,724
  • 12
  • 9
  • Thanks. This adds the panels to the frame (although I'm a little confused about __init__ as opposed on OnInit). However, the def changeIntroPanel still does not work. The problem is that it needs to refer to the MainFrame class, but it can't. – intl Feb 20 '14 at 07:00
  • Update: I can sort of circumvent the problem by binding the function in my MainAPP __init__ and then just bringing def changeIntroPanel into MainApp itself. Is this the only way or is there a nicer way of keeping the function in Panel1 and working with that? – intl Feb 20 '14 at 07:18
  • 1
    @intl kind of understand your purpose, please check the update answer. – Jerry_Y Feb 20 '14 at 07:34
  • 1
    This is fantastic. Thanks so much for the help - you make the internet awesome! As advice, what is a better idea? If I were to have many functions who would need to work with each other, should I just have the functions in the MainFrame? Or is having them separately in different classes fine? – intl Feb 20 '14 at 07:42
  • It depends on your implementation and hard to tell which way is better. But I think both good as long as ther are well organized. – Jerry_Y Feb 20 '14 at 08:18