Search code examples
inheritancewxpythonframe

Second wx.Frame inside a wx.Frame - messed up layout


I have a wx.python program which uses a wx.Frame in a class called Main. On this, I have a Menu bar, with "preferences", the idea is to click this menu to open up another wx.Frame for config boxes etc. However the problem is that although I believe the coding is correct, the wx.Frame widgets and BoxSizer layout, doesn't display correctly and is all crammed into the top left corner overlapping each other.

Similarly, I the Main class contains a method called openFile. I call this in my Preferences class, I tried using class inheritance, but don't think I got it correct, class Main(wx.Frame), class Preferences(Main).

  • wx.Frame child, above the parent doesn't show up correctly, layout is all crammed.
  • Think my class inheritance is wrong :(

Thanks.

Image enter image description here

#!/usr/bin/python

import wx,os

class Main(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(680, 300))

        appName = ''
        dirName = ''
        toolDir = ''
        dirname = ''

        #FILE MENU
        fileMenu = wx.Menu()  #create menu for file
        menuOpen = fileMenu.Append(wx.ID_OPEN, "&Open\tCtrl+O"," Open a file to edit")  #add open to File
        menuExit = fileMenu.Append(wx.ID_EXIT, "E&xit\tCtrl+Q"," Terminate the program")  #add exit to File


        #PREF MENU
        prefMenu = wx.Menu() #create pref menu
        menuPref = prefMenu.Append(wx.ID_ANY, "Preferences", "Open preferences")

        #MENUBAR
        menuBar = wx.MenuBar()
        menuBar.Append(fileMenu,"&File") # Adding the "filemenu" to the MenuBar
        menuBar.Append(prefMenu, "&Preferences")
        self.SetMenuBar(menuBar)  # Adding the MenuBar to the Frame content.

        self.setStatusBar = self.CreateStatusBar()
        self.setStatusBar.SetStatusText('Ready')

        #MENU EVENTS
        self.Bind(wx.EVT_MENU, self.openFile, menuOpen)
        self.Bind(wx.EVT_MENU, self.OnPref, menuPref)
        self.Bind(wx.EVT_MENU, self.OnExit, menuExit)


        #LAYOUT BOXES
        panel = wx.Panel(self)
        panel.SetBackgroundColour('#ededed')
        vBox = wx.BoxSizer(wx.VERTICAL)
        hBox1 = wx.BoxSizer(wx.HORIZONTAL)

        #FILE TEXT AND LOAD
        hBox1.Add(wx.StaticText(panel, label="File:"), flag=wx.TOP, border=3)
        self.fileTxt = wx.TextCtrl(panel, style=wx.TE_READONLY|wx.TE_RICH)
        #self.Bind(wx.EVT_LEFT_DOWN, self.openFile, self.fileTxt)
        hBox1.Add(self.fileTxt, 1, flag=wx.LEFT, border=10)
        loadBtn = wx.Button(panel, -1, "Load")
        self.Bind(wx.EVT_BUTTON, self.loadClick, loadBtn)
        hBox1.Add(loadBtn, 0, flag=wx.LEFT, border=10)
        vBox.Add(hBox1, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=10)


        panel.SetSizer(vBox)

        #GUI EVENTS
    def loadClick(self,e): # loads the app, and changes directory to the app path 
        global dirName, appName
        self.setStatusBar.SetStatusText('File ' + appName + ' loaded') 
        self.progressBox.SetValue(appName + ' loaded\n') # updates progress box
        os.system('cd ' + dirName) 
        self.progressBox.AppendText('Directory set to ' + dirName + '\n') #appends progress box

    def clearBtnClick(self,e): #clears all fields and bar
        self.progressBox.SetValue("")
        self.fileTxt.SetValue("")
        self.setStatusBar.SetStatusText('Ready')

    def exitBtnClick(self,e):
        self.Close(True)

        #MENU ITEM EVENTS
    def OnAbout(self,e):
        dlg = wx.MessageDialog(self, "test program", "About", wx.OK)  #create a dialog (dlg) box to display the message, and ok button
        dlg.ShowModal()  #show the dialog box, modal means cannot do anything on the program until clicks ok or cancel
        dlg.Destroy()  #destroy the dialog box when its not needed

    def OnExit(self,e):
        self.Close()  #on menu item select, close the app frame.

    def openFile(self,e): 
        global dirname
        dialog = wx.FileDialog(self, "Choose a file to open", self.dirname, "", "*.txt", wx.OPEN) #open the dialog box to open file
        if dialog .ShowModal() == wx.ID_OK:
            directory, filename = dlg.GetDirectory(), dlg.GetFilename()
            self.filePath = '/'.join((directory, filename))
            self.fileTxt.SetValue(self.filePath) #set text field to file path
            global dirName, appName #
            dirName = (directory)
            appName = (filename)

    def OnPref(self,e):
        pref = prefWindow()
        pref.Show()   

    def toggleStatusBar(self,e):
        if self.menuStat.IsChecked():
            self.setStatusBar.Show()
        else:
            self.setStatusBar.Hide()

class prefWindow(Main):

    def __init__(self):
        wx.Frame.__init__(self, wx.GetApp().TopWindow) 

        self.Show()
        self.SetTitle('Preferences')
        self.SetSize((280, 300))

        panelPref = wx.Panel(self)
        panelPref.SetBackgroundColour('#ededed')
        vBox = wx.BoxSizer(wx.VERTICAL)
        hBox1 = wx.BoxSizer(wx.HORIZONTAL)

        hBox1.Add(wx.StaticText(panelPref, label="Tools Directory:"), flag=wx.TOP, border=3)
        self.toolDir = wx.TextCtrl(panelPref, style=wx.TE_READONLY|wx.TE_RICH)
        hBox1.Add(self.toolDir, 0, flag=wx.LEFT, border=10)
        browseBtn = wx.Button(panelPref, -1, "Browse")
        self.Bind(wx.EVT_BUTTON, Main.openFile, browseBtn)
        hBox1.Add(browseBtn, 0, flag=wx.LEFT, border=10)
        vBox.Add(hBox1, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM, border=10)

        vBox.Add((-1, 5))

        panelPref.SetSizer(vBox)  


class MyApp(wx.App):
    def OnInit(self):
        frame = Main(None, -1, 'Test')
        frame.Show(True)
        frame.Centre()
        return True

app = MyApp(0)
app.MainLoop()

if __name__ == '__main__':
    main()

Solution

  • In your prefWindow class, calling self.show() before sizer layout was the problem. You need to call self.show() after sizer layout.

    class prefWindow(Main):
    
        def __init__(self):
            wx.Frame.__init__(self, wx.GetApp().TopWindow)
    
            #self.Show()        
            self.SetTitle('Preferences')
            self.SetSize((280, 300))
    
            panelPref = wx.Panel(self)
            panelPref.SetBackgroundColour('#ededed')
            vBox = wx.BoxSizer(wx.VERTICAL)
            hBox1 = wx.BoxSizer(wx.HORIZONTAL)
    
            hBox1.Add(wx.StaticText(panelPref, label="Tools Directory:"), flag=wx.TOP, border=3)
            self.toolDir = wx.TextCtrl(panelPref, style=wx.TE_READONLY|wx.TE_RICH)
            hBox1.Add(self.toolDir, 0, flag=wx.LEFT, border=10)
            browseBtn = wx.Button(panelPref, -1, "Browse")
            self.Bind(wx.EVT_BUTTON, Main.openFile, browseBtn)
            hBox1.Add(browseBtn, 0, flag=wx.LEFT, border=10)
            vBox.Add(hBox1, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM, border=10)
    
            vBox.Add((-1, 5))
    
            panelPref.SetSizer(vBox)
            self.Show() ## call Show() here