pythonwxpythonboxsizer

Overlapping widgets (controls) within wxPython BoxSizer


I'm adding elements to a horizontal wx.BoxSizer, but instead of being layed-out next to each other, they are displayed on top of each other (all are placed in pixel position (0,0) of the parent panel).

Below are shortened versions of the files (the relevant parts):

main.py:

import wx
from frm_users import UsersForm

class MainFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "My App Title", size=(1200, 800))
        self.panel = wx.Panel(self, wx.ID_ANY)
        self.statusbar = self.CreateStatusBar(2)
        self.statusbar.SetStatusWidths([-1, 60])

    # this event is bound to a menu item I construct elsewhere
    def onUsers(self, event=None):
        frmUsers = UsersForm(self.panel)


if __name__ == "__main__":    
    app = wx.App(False)
    frame = MainFrame()    
    frame.Show()
    app.MainLoop()

frm_users.py:

from dbmodel import OlvUsers, Users
import forms_controller
import wx

class UsersForm(wx.Panel):
    def __init__(self, parent):
        # parent here is the panel

        toolbox = forms_controller.getToolboxSizer(self, parent)
        parent.SetSizer(toolbox)


    def onSearch(self, event=None):
        print("Searching")

forms_controller.py:

import wx


def getToolboxSizer(parent, frame):
    # frame is a panel usually
    toolboxSizer = wx.BoxSizer(wx.HORIZONTAL)
    toolboxSizer.AddSpacer(5)

    font = wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD)
    # create the search related widgets
    searchByLbl = wx.StaticText(frame, label="Search By:")
    searchByLbl.SetFont(font)
    toolboxSizer.Add(searchByLbl, 0, wx.ALL, 5)

    cat = ["Author", "Title", "ISBN", "Publisher"]
    categories = wx.ComboBox(frame, value="Author", choices=cat)
    toolboxSizer.Add(categories, 0, wx.ALL, 5)

    search = wx.SearchCtrl(frame, style=wx.TE_PROCESS_ENTER)
    search.Bind(wx.EVT_TEXT_ENTER, parent.onSearch)
    toolboxSizer.Add(search, 0, wx.ALL, 5)

    return toolboxSizer

What am I missing?


Solution

  • In main.py, the instance of UsersForm is not inside of a sizer. Panels do not fill their parent automatically except when they are the sole child of a wx.Frame. To make this work, you should add frmUsers to a sizer that is associated with the panel in the frame.

    I think there may also be an issue in getToolboxSizer since the widgets there appear to be getting added directly to the frame instead of a panel. You usually want to add child widgets to a Panel so that tabbing will work correctly.

    I would probably change onUsers to the following:

    def onUsers(self, event=None):
        child_sizer = getToolboxSizer(self.panel)
        self.main_sizer.Add(child_sizer, 0, wx.ALL, 5)
    

    Then update getToolboxSizer so it doesn't place all its widgets on the parent since the parent will now be a panel.