In wxPython, I'm having trouble centering a sub-panel that I've created to have a fixed aspect ratio.
To control the aspect ratio, the sub-panel needs to capture the Size event and then do an explicit SetSize. So, I've done that and it works well. Unfortunately, when I embed this sub-panel into another panel (using a sizer), the wx.ALIGN_CENTER_HORIZONTAL flag doesn't work.
Apparently, the sizer tells my sub-panel that it has the whole width to fit within. When my window doesn't use the whole width, then the sizer doesn't adjust. Here is a simplified version of my code that shows the problem:
import wx
ROWS = 6
COLS = 25
class TestPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, -1)
label = wx.StaticText(self, -1, 'Label')
grid = TestGrid(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(label, 0, flag=wx.ALIGN_CENTER_HORIZONTAL)
sizer.Add(grid, 1, flag=wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND)
self.SetSizer(sizer)
class TestGrid(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, -1)
self.SetBackgroundColour(wx.BLUE)
self.Bind(wx.EVT_SIZE, self.OnSize)
def OnSize(self, event):
w, h = self.GetSizeTuple()
delta = min(w // COLS, h // ROWS)
self.SetSize((COLS*delta, ROWS*delta))
self.Refresh()
if __name__ == '__main__':
app = wx.App()
frame = wx.Frame(None, -1, "Test", size=(600, 200))
panel = TestPanel(frame)
frame.Show(True)
app.MainLoop()
This is a screen capture:
As VZ explained in his answer, your wxEVT_SIZE
handler isn't a very good idea. Remove it. When using sizers, you have to work within the sizer infrastructure to achieve what you want.
You want your TestGrid
to fill as much space as possible within its parent, while maintaining a certain aspect ratio; that's exactly what wx.SHAPED
is for (combined with a proportion
greater than 0, which you already have). So, you should add grid
to the sizer like this:
sizer.Add(grid, 1, flag=wx.ALIGN_CENTER_HORIZONTAL|wx.SHAPED)
The only other thing you need to do is tell the sizer what your desired aspect ratio is. The easiest way is to set an initial size for your TestGrid
(before it's added to the sizer); for example, set the size of its wxPanel
base:
wx.Panel.__init__(self, parent, -1, size=(COLS*7, ROWS*7))
That's all there is to it.
(I'm just guessing the Python syntax, so ignore any obvious errors :-) )