Robin Dunn wrote:
Quoting James Bigler <bigler@cs.utah.edu>:
...SNIP CODE...
# Create the panel
self.panel = wx.Panel(self, -1, size=(300,400))
self.panel.SetBackgroundColour(\\\"green\\\")
box = wx.BoxSizer(wx.HORIZONTAL)
box.Add(self.panel, 1, wx.EXPAND)
# !!! This resizes panel !!!
#self.SetSizerAndFit(box)
...SNIP CODE...
I tried you code and the panel doesn\\\'t start off with the right size.
Plus the status bar doesn\\\'t appear until I make the window long enough
(looks like to be around the requested height of the panel).
What I don\\\'t get is why the sizer forces the min size to be (300,400).
I even tried to force it to be smaller, but the sizer overrides it
somehow.
Hi James,
I added:
print \\\"Size = %s\\\" % self.panel.GetSize()
and got the results:
Size = (300, 400)
did you get something else?
This is the size before the sizer does a layout. If you look at the size after the frame has been shown and the layout happens then you'll see the problem James is having. Without the SetSizer* call in your sample the default frame size is being used and so the panel is being resized in the first layout.
To address the other problems there are a couple things that needs to be understood about sizers and default sizes.
First, SetSizerAndFit is a convenience function that simply calls self.SetSizer(sizer) and sizer.SetSizeHints(self), so when you call that with the frame you are setting the min size of the frame based on the current minsize needed by the sizer, so that is why the frame can't be resized smaller. So changing that to just self.SetSizer and a separate call to self.Fit will set the initial size correctly based on the sizer's min size, but still allow the frame to get smaller.
So, one of the things I had to note about your comment is that it creates a min size for the *frame*. I was changing the min size of the panel, but not changing the min size of the frame. Because of this, I couldn't size the panel down.
Second, when a sizer calculates the space it needs it calls the GetSBestFittingSize method on each widget that will return a size based on the widget's min size (if set) and a calculated best size. But for things like the panel which has no children, no sizer, and no set minsize there is no way to calculate a best size so the current size is used instead. For widgets that will have a flexible size in the sizer this means that as soon as the sizer changes the size larger, then the best size is larger and the sizer may not make it smaller (depending on the sizer parameters.) Also, for most widgets passing a size to the constructor will set the min size to that value.
So in the case of this example where you want the initial size to not be the min size, you need to set the initial size in some other way than by letting the sizer do it. See attached sample for one way to do it.
The problem with this is that it did weird things when I had a wxGLCanvas in the panel. Something would cause a SIZE event and it would pop down to the min size of (20, 20).
Here's the relevant block of code that sets the size of the panel, does a fit to get everything the correct size in the beginning and then changes the min size of the panel and frame.
# Create the panel
self.panel = wx.Panel(self, -1)
self.panel.SetBackgroundColour(wx.NamedColor("green"))
box = wx.BoxSizer(wx.HORIZONTAL)
box.Add(self.panel, 1, wx.EXPAND)
# Set the initial sizes I want
self.panel.SetSize((300, 400))
self.SetSizerAndFit(box)
# Now fix the min sizes of the panel and frame
self.panel.SetMinSize((20,20))
self.SetMinSize(self.GetSize() - self.panel.GetSize()
+ self.panel.GetMinSize())
This also does the right thing when I have a wxGLCanvas inside the panel. I've attached the latest code.
Thank you Robin and Ray!
James
resize2.py (2.28 KB)
···
ray@raymondsmith.com wrote: