SetMinSize() on both grid widgets ->helps<- align both grid widgets. But does not guarantee it, in this case, because CalendarHeaderPanel is managed by HeaderPanel.Sizer and the RosterPanel by a different sizer, DataPanel.Sizer.
In this case each Panel sizes their children grid widgets without regard to the other subPanel. So alignment is not guaranteed. If you set the MinWidth of VacationHeaderPanel to 300 and the VacationPanel MinWidth to 100 you could see HeadersPanel potentially different in size then DataPanel depending the presence of other children or data.
-------------------------------------
Is it the proper way? How would you do it?
Well as person who codes for a hobby and for fun, I am not one who is authoritative on what is the proper way. On “proper ways” I defer to the MBFL principle of Python. Why are things a certain way in Python? Because Guido says so. Why are things a certain way in wxPython? Because Robin says so. Robin suggests to first work from inner layouts to outer layouts.
My test for your grid in the frame is following Robin’s advice on coding from inner widget layouts first then inject the working inner working layout into larger layouts. It is also why my helper code to your question was broken down into so many smaller panels within panels within panels.
I also broke down the layouts into panels in panels in panels presuming it will be easier to put child “control” widgets around your grids if you wanted to (in the future). Additionally I did it to get a clear definition from you. The "How would “I” do it depends on why I’d do it. The “why” here was for clarity to you. BUT…
I like to put similar functionality in a “grouping” widget. Meaning you say the CALENDAR HEADER PANEL and the ROSTER PANEL where of the same functional concern. In that case I would NOT put the CALENDAR HEADER PANEL in a “HEADER PANEL” with a separate functional concern VACATION HEADER PANEL (as we both did horizontally in the “HEADER PANEL”).
I would put the CALENDAR HEADER PANEL and the ROSTER PANEL in a vertical panel together as those widgets are functionally linked.
Taking this further I would re-factor to get rid of the CALENDAR HEADER PANEL and the ROSTER PANEL and make a CALENDAR_ROSTER PANEL instead, with a vertical boxsizer holding the CALENDAR HEADER GRID and the ROSTER GRID. Why? because their widths are linked and they refer to the same data.
I would put the VACATION HEADER GRID and the VACATION GRID in a second vertical box-sized VACATION PANEL so both of those grid’s with the same data and widths are linked.
BUT… If you want all four wx.grids to be both vertically and horizontally aligned. They should be in ONE sizer, that NOT being a wx.BoxSizer but a wx.GridSizer or another Sizer TYPE.
If that is the case, THEN I’d re-factor again, If all four grids are linked in usage and data. I would get rid of the HEADERS PANEL, DATA PANEL, CALENDAR HEADER PANEL, VACATION HEADER PANEL, VACATION PANEL and ROSTER PANEL and put everything in a FlexGridSizer on the NOTEBOOK PAGE MAIN PANEL. But that is if each grid’s data, visually frozen or not, is linked in how the user views the data.
---------------
As to the 3rd panel not showing. First the frame, when init’d, should have an initial size wider then a two-wxgrid-wide layout.
Second. Remember this one. Not all widgets have a default initial size of something greater then (0,0).
Which means when you use sizers with wx.EXPAND and your dev test panel has no children widgets OR a child widget that defaults to size (0,0) the panel could be “fitted” to that size automatically meaning (0,0) even if it has an wx.Boxsizer.Add( widget, PROPORTION=wx.EXPAND, flags=wx.EXPAND, border). I think this is buggy but following Robin’s layout methods solves the problem.
It is why when setting up layouts put at least one “test” widget onto a panel. I think the wx.grid default might be (0,0) if it has no data. I used StaticText widgets to handle this “issue” in the example module I sent you. my previous recommendation of using a wx.TextCtrl is also a good test widget because it allows you see your interaction with it.
----------------------------------------------------
This line could be your sneaky bug. I see (self, left_panel), two separate parent widgets. You could be have a parent/layout clash in there. Perhaps your putting a context menu onto on “self” instead of “left_panel” or something like that.
binder = cxt_functions.AddGridFunctions(self, left_panel) #bind some context menu functions to this grid