I find that wxGlade is very useful for designing the layout of a UI. It allows you to easily test how the UI responds to resizing of a frame or dialog.
I have attempted to create a similar layout to what you show. wxGlade does not have direct support for ObjectListView
controls, so for simplicity I have substituted a ListCtrl
as it has a similar appearance.
Here is the code it generates:
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
#
# generated by wxGlade 1.0.5 on Thu Apr 13 08:58:42 2023
#
import wx
# begin wxGlade: dependencies
# end wxGlade
# begin wxGlade: extracode
# end wxGlade
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
# begin wxGlade: MyFrame.__init__
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.SetSize((750, 550))
self.SetTitle("frame")
# Menu Bar
self.frame_menubar = wx.MenuBar()
wxglade_tmp_menu = wx.Menu()
wxglade_tmp_menu.Append(wx.ID_ANY, "Exit", "")
self.frame_menubar.Append(wxglade_tmp_menu, "File")
self.SetMenuBar(self.frame_menubar)
# Menu Bar end
self.frame_statusbar = self.CreateStatusBar(1)
self.frame_statusbar.SetStatusWidths([-1])
# statusbar fields
frame_statusbar_fields = ["frame_statusbar"]
for i in range(len(frame_statusbar_fields)):
self.frame_statusbar.SetStatusText(frame_statusbar_fields[i], i)
self.main_panel = wx.Panel(self, wx.ID_ANY)
main_sizer = wx.BoxSizer(wx.VERTICAL)
self.notebook = wx.Notebook(self.main_panel, wx.ID_ANY)
main_sizer.Add(self.notebook, 1, wx.EXPAND, 0)
self.ledger_pane = wx.Panel(self.notebook, wx.ID_ANY)
self.notebook.AddPage(self.ledger_pane, "Ledger")
ledger_main_sizer = wx.BoxSizer(wx.VERTICAL)
ledger_search_sizer = wx.BoxSizer(wx.HORIZONTAL)
ledger_main_sizer.Add(ledger_search_sizer, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 4)
ledger_search_label = wx.StaticText(self.ledger_pane, wx.ID_ANY, "Search By:")
ledger_search_sizer.Add(ledger_search_label, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 2)
self.ledger_search_combo_box = wx.ComboBox(self.ledger_pane, wx.ID_ANY, choices=[], style=wx.CB_DROPDOWN)
ledger_search_sizer.Add(self.ledger_search_combo_box, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 4)
self.ledger_search_text_ctrl = wx.TextCtrl(self.ledger_pane, wx.ID_ANY, "")
ledger_search_sizer.Add(self.ledger_search_text_ctrl, 0, wx.ALIGN_CENTER_VERTICAL, 0)
self.ledger_list_ctrl = wx.ListCtrl(self.ledger_pane, wx.ID_ANY, style=wx.LC_HRULES | wx.LC_REPORT | wx.LC_VRULES)
self.ledger_list_ctrl.AppendColumn("A", format=wx.LIST_FORMAT_LEFT, width=-1)
self.ledger_list_ctrl.AppendColumn("B", format=wx.LIST_FORMAT_LEFT, width=-1)
self.ledger_list_ctrl.AppendColumn("C", format=wx.LIST_FORMAT_LEFT, width=-1)
ledger_main_sizer.Add(self.ledger_list_ctrl, 1, wx.ALL | wx.EXPAND, 4)
ledger_button_sizer = wx.BoxSizer(wx.HORIZONTAL)
ledger_main_sizer.Add(ledger_button_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.BOTTOM | wx.TOP, 4)
self.ledger_add_button = wx.Button(self.ledger_pane, wx.ID_ANY, "Add")
ledger_button_sizer.Add(self.ledger_add_button, 0, wx.RIGHT, 8)
self.ledger_edit_button = wx.Button(self.ledger_pane, wx.ID_ANY, "Edit")
ledger_button_sizer.Add(self.ledger_edit_button, 0, wx.RIGHT, 8)
self.ledger_delete_button = wx.Button(self.ledger_pane, wx.ID_ANY, "Delete")
ledger_button_sizer.Add(self.ledger_delete_button, 0, wx.RIGHT, 8)
self.ledger_show_all_button = wx.Button(self.ledger_pane, wx.ID_ANY, "Show All")
ledger_button_sizer.Add(self.ledger_show_all_button, 0, 0, 0)
self.ledger_pane.SetSizer(ledger_main_sizer)
self.main_panel.SetSizer(main_sizer)
self.Layout()
# end wxGlade
# end of class MyFrame
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, wx.ID_ANY, "")
self.SetTopWindow(self.frame)
self.frame.Show()
return True
# end of class MyApp
if __name__ == "__main__":
app = MyApp(0)
app.MainLoop()
For the parent/child hierarchy:
The Frame is the parent of the main Panel.
The main Panel is the parent of the Notebook.
The Notebook is the parent of the Panels that comprise its panes/pages.
Each pane is the parent of all the controls it contains.
When adding an item or sizer to a vertical BoxSizer, the proportion argument specifies how the much that item will be stretched vertically. In my example only the ListCtrl needs to be stretched vertically, so its proportion argument is set to one. The search sizer and button sizer do not need to stretch vertically, so their proportion arguments are set to zero.
I hope you can adapt ideas from this example to your design.
Tested using Python 3.10.6 + wxPython 4.2.0 gtk3 (phoenix) wxWidgets 3.2.0 on Linux Mint 21.1