I created a simple test case to resize a panel.
The layout contains a main frame and 3 panels
The frame contains a vertical boxsizer that contains 2 components
The first component is a horizontal boxsizer
The second component is a panel containing the “Close” button
The horizontal boxsizer contains 2 panels
I arbitrarily create the 2 panels having widths of ratio 1:2
When the program runs, I want the width of the right panel to be equal to the height of the right panel
and the rest of the remaining width space to be the width of the left panel.
I implemented this using CallAfter() for the Maximize event
The program runs. No changes are made to any of the 2 panels.
If I omit the Layout() method, I see that the size of the right panel changes, but the layout does not occur.
Can someone explain how this is supposed to work?
Thanks
Python 3.10.6 on linux, wxPython 4.0.7 gtk3 (phoenix) wxWidgets 3.0.
resize-panels.py (4.7 KB)
In the end, I resolved this issue by doing the layout of the panels manually.
I called GetSize, GetPosition, SetSize and SetPosition and was good to go.
Would that work?
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, parent=None, title='Resize Panels', style= wx.CAPTION | wx.CLOSE_BOX | wx.RESIZE_BORDER)
....
self.h_framesizer.Add(self.rightbuttonpanel, 0, flag=wx.EXPAND)
....
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Layout()
self.Show(True)
def OnSize(self, event):
height = self.rightbuttonpanel.GetSize()[1]
self.rightbuttonpanel.SetMinSize( (height, height) )
self.Layout()
Hi Dietmar,
That solution did not work.
The panels were not automatically re-sized.
Thanks
I’m on Windows where it was working.
I have just tried on Ubuntu.
There I had to add a wx.CallLater(100, self.OnSize, None) for the initial resizing. Also, the size calculation was not triggered between Maximize and resizing. It seems initialization and the order of events are different between the platforms. But anyway, proportion=0 and SetMinSize are the way to go.
Is this the solution that works for you?
class MainFrame(wx.Frame):
def init(self):
wx.Frame.init(self, parent=None, title=‘Resize Panels’, style= wx.CAPTION | wx.CLOSE_BOX)
self.leftbuttonpanel = LeftButtonPanel(self)
self.rightbuttonpanel = RightButtonPanel(self)
self.actionbuttonpanel = ActionButtonPanel(self)
self.h_framesizer = wx.BoxSizer(wx.HORIZONTAL)
self.h_framesizer.Add(self.leftbuttonpanel, 1, flag=wx.EXPAND)
self.h_framesizer.Add(self.rightbuttonpanel, 2, flag=wx.EXPAND)
self.v_framesizer = wx.BoxSizer(wx.VERTICAL)
self.v_framesizer.Add(self.h_framesizer, 0, flag=wx.EXPAND)
self.v_framesizer.Add(self.actionbuttonpanel, 0, flag=wx.EXPAND)
self.SetSizer(self.v_framesizer)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Maximize()
self.Show(True)
def _OnSize(self):
height = self.rightbuttonpanel.GetSize()[1]
self.rightbuttonpanel.SetMinSize( (height, height) )
self.Layout()
def OnSize(self, event):
wx.CallAfter(100, self._OnSize, None)
On my Mate machine running Ubuntu 22.04 LTS, the following error occurs when CallAfter is executed
Traceback (most recent call last):
File “/usr/local/src/python/resize-panels.py”, line 29, in OnSize
wx.CallAfter(100, self._OnSize, None)
File “/usr/lib/python3/dist-packages/wx/core.py”, line 3275, in CallAfter
assert callable(callableObj), “callableObj is not callable”
AssertionError: callableObj is not callable
Try wx.CallAfter(100, self._OnSize) and add it also to the end of the __init__method.
Hi Dietmar,
I get the following error when CallAfter is executed
Traceback (most recent call last):
File “/usr/local/src/python/resize-panels.py”, line 29, in OnSize
wx.CallAfter(100, self._OnSize, None)
File “/usr/lib/python3/dist-packages/wx/core.py”, line 3275, in CallAfter
assert callable(callableObj), “callableObj is not callable”
AssertionError: callableObj is not callable
Omit the None. Your _OnSize method does not accept arguments other than self.
Sorry, should have written wx.CallLater(100, self._OnSize), like above, not wx.CallAfter. 100 is the delay in ms.
Hi Dietmar,
There is no change to the panels.
They are not automatically resized
This is the solution I tried.
class MainFrame(wx.Frame):
def init(self):
wx.Frame.init(self, parent=None, title=‘Resize Panels’, style= wx.CAPTION | wx.CLOSE_BOX)
self.leftbuttonpanel = LeftButtonPanel(self)
self.rightbuttonpanel = RightButtonPanel(self)
self.actionbuttonpanel = ActionButtonPanel(self)
self.h_framesizer = wx.BoxSizer(wx.HORIZONTAL)
self.h_framesizer.Add(self.leftbuttonpanel, 1, flag=wx.EXPAND)
self.h_framesizer.Add(self.rightbuttonpanel, 2, flag=wx.EXPAND)
self.v_framesizer = wx.BoxSizer(wx.VERTICAL)
self.v_framesizer.Add(self.h_framesizer, 1, flag=wx.EXPAND)
self.v_framesizer.Add(self.actionbuttonpanel, 0, flag=wx.EXPAND)
self.SetSizer(self.v_framesizer)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Maximize()
self.Show(True)
def _OnSize(self):
height = self.rightbuttonpanel.GetSize()[1]
self.rightbuttonpanel.SetMinSize( (height, height) )
self.Layout()
def OnSize(self, event):
wx.CallLater(100, self._OnSize)
Thanks
With
self.h_framesizer.Add(self.rightbuttonpanel, 0, flag=wx.EXPAND) and wx.CallLater at the end of __init__?
Hi Dietmar,
The panels are automatically resized.
Excellent!
Thank you very much for your help and patience
This is the solution that works for me.
class MainFrame(wx.Frame):
def init(self):
wx.Frame.init(self, parent=None, title=‘Resize Panels’, style= wx.CAPTION | wx.CLOSE_BOX)
self.leftbuttonpanel = LeftButtonPanel(self)
self.rightbuttonpanel = RightButtonPanel(self)
self.actionbuttonpanel = ActionButtonPanel(self)
self.h_framesizer = wx.BoxSizer(wx.HORIZONTAL)
self.h_framesizer.Add(self.leftbuttonpanel, 1, flag=wx.EXPAND)
self.h_framesizer.Add(self.rightbuttonpanel, 0, flag=wx.EXPAND)
self.v_framesizer = wx.BoxSizer(wx.VERTICAL)
self.v_framesizer.Add(self.h_framesizer, 1, flag=wx.EXPAND)
self.v_framesizer.Add(self.actionbuttonpanel, 0, flag=wx.EXPAND)
self.SetSizer(self.v_framesizer)
self.Maximize()
self.Show(True)
wx.CallLater(100, self.OnReSize)
def OnReSize(self):
height = self.rightbuttonpanel.GetSize()[1]
self.rightbuttonpanel.SetMinSize( (height, height) )
self.Layout()