Resizing the main panel

2,176 views
Skip to first unread message

James Bigler

unread,
Jul 12, 2006, 6:55:16 PM7/12/06
to wxPytho...@lists.wxwidgets.org
Here's some demo code. There is a menu, a status bar, and a panel with a green
background. I want the panel to resize when the screen gets bigger or smaller.
Currently the min size gets set when I call SetSize(), so you can't make it
smaller.

Any help or pointers would be appreciated.

Thanks,
James Bigler

James Bigler

unread,
Jul 12, 2006, 7:01:18 PM7/12/06
to wxPytho...@lists.wxwidgets.org
Just realized I forgot to attach the demo code.

James

resize.py

James Bigler

unread,
Jul 12, 2006, 7:38:11 PM7/12/06
to wxPytho...@lists.wxwidgets.org
r...@raymondsmith.com wrote:
> Here is some modified code that I think does what you want:
..SNIP..

Yes, you discovered what I did eventually. The OnSize event was causing part of
the problem. I needed to add event.Skip(True) to make it work on making it bigger.

I still can't make it smaller than the initial size, however. I even tried to
change the minimum size after the window was shown, but that didn't have an effect.

def OnSize(self, event):
if (not self.panel.minSizeSet):
self.panel.SetMinSize(wx.Size(20,20))
self.panel.minSizeSet = True

self.SetStatusText("Size = %s" % (self.panel.GetSize(),) )
event.Skip(True)

So I want the panel to be a certain initial size, but I want to be able to make
it bigger or smaller afterwards.

Thanks,
James

r...@raymondsmith.com

unread,
Jul 12, 2006, 7:16:07 PM7/12/06
to wxPytho...@lists.wxwidgets.org
Quoting James Bigler <big...@cs.utah.edu>:

> Just realized I forgot to attach the demo code.
>
> James

Here is some modified code that I think does what you want:


---------------
import wx

class MyApp(wx.App):
def OnInit(self):
frame = Frame(parent=None, title=\'Resize Panel\')
frame.Show()
self.SetTopWindow(frame)
return True

class Frame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent=parent, title=title)

# Setup menu bar
menuBar = wx.MenuBar()
menu1 = wx.Menu()
self.Bind(wx.EVT_MENU, self.OnQuit, menu1.Append(wx.NewId(),
\"&Quit\"))
menuBar.Append(menu1, \"&File\")
menu2 = wx.Menu()
self.Bind(wx.EVT_MENU, self.OnAbout, menu2.Append(wx.NewId(),
\"About Me\"))
menuBar.Append(menu2, \"&Help\")
self.SetMenuBar(menuBar)

# Create status bar
self.CreateStatusBar()
self.SetStatusText(\"Welcome to wxPython!\")

# Create the panel
self.panel = wx.Panel(self, -1, size=wx.Size(300,400))
self.panel.SetBackgroundColour(wx.NamedColor(\"green\"))

box = wx.BoxSizer(wx.HORIZONTAL)
box.Add(self.panel, 1, wx.EXPAND)
self.SetSizerAndFit(box)

print \"Min Size = %s\" % self.panel.GetMinSize()
print \"Max Size = %s\" % self.panel.GetMaxSize()
print \"Best Size = %s\" % self.panel.GetBestSize()

def OnQuit(self, event):
self.Close()

def OnAbout(self, event):
wx.MessageBox(\"This is a test program to show how to resize
the main panel. I want the green panel to change size when the screen
is resized bigger and smaller than the original. \",
\"About Me\", wx.OK | wx.ICON_INFORMATION, self)


if __name__ == \'__main__\':
app = MyApp(False)
app.MainLoop()

-----------------


Regards,

Ray Smith
http://RaymondSmith.com

r...@raymondsmith.com

unread,
Jul 12, 2006, 7:49:35 PM7/12/06
to wxPytho...@lists.wxwidgets.org
Quoting James Bigler <big...@cs.utah.edu>:

> I still can\'t make it smaller than the initial size, however. I even
> tried to change the minimum size after the window was shown, but that
> didn\'t have an effect.
>
> def OnSize(self, event):
> if (not self.panel.minSizeSet):
> self.panel.SetMinSize(wx.Size(20,20))
> self.panel.minSizeSet = True
>
> self.SetStatusText(\"Size = %s\" % (self.panel.GetSize(),) )
> event.Skip(True)
>
> So I want the panel to be a certain initial size, but I want to be able
> to make it bigger or smaller afterwards.


Hi James,

One way is to set the frame to a default size and don\'t do the:
self.SetSizerAndFit(box)

See code below:

-----------
import wx

class MyApp(wx.App):
def OnInit(self):
frame = Frame(parent=None, title=\'Resize Panel\')
frame.Show()
self.SetTopWindow(frame)
return True

class Frame(wx.Frame):
def __init__(self, parent, title):

wx.Frame.__init__(self, parent=parent, title=title, size=(300,400))

# Setup menu bar
menuBar = wx.MenuBar()
menu1 = wx.Menu()
self.Bind(wx.EVT_MENU, self.OnQuit, menu1.Append(wx.NewId(),
\"&Quit\"))
menuBar.Append(menu1, \"&File\")
menu2 = wx.Menu()
self.Bind(wx.EVT_MENU, self.OnAbout, menu2.Append(wx.NewId(),
\"About Me\"))
menuBar.Append(menu2, \"&Help\")
self.SetMenuBar(menuBar)

# Create status bar
self.CreateStatusBar()
self.SetStatusText(\"Welcome to wxPython!\")

# Create the panel
self.panel = wx.Panel(self, -1)
self.panel.SetBackgroundColour(\"green\")

box = wx.BoxSizer(wx.HORIZONTAL)
box.Add(self.panel, 1, wx.EXPAND)

# !!! This resizes the frame !!!
#self.SetSizerAndFit(box)

print \"Min Size = %s\" % self.panel.GetMinSize()
print \"Max Size = %s\" % self.panel.GetMaxSize()
print \"Best Size = %s\" % self.panel.GetBestSize()

def OnQuit(self, event):
self.Close()

def OnAbout(self, event):
wx.MessageBox(\"This is a test program to show how to resize
the main panel. I want the green panel to change size when the screen
is resized bigger and smaller than the original. \",
\"About Me\", wx.OK | wx.ICON_INFORMATION, self)


if __name__ == \'__main__\':
app = MyApp(False)
app.MainLoop()

----------------

Regards,

Ray Smith
http://RaymondSmith.com

James Bigler

unread,
Jul 13, 2006, 2:34:11 AM7/13/06
to wxPytho...@lists.wxwidgets.org
r...@raymondsmith.com wrote:
> Quoting James Bigler <big...@cs.utah.edu>:
>
>> I still can\'t make it smaller than the initial size, however. I even
>> tried to change the minimum size after the window was shown, but that
>> didn\'t have an effect.
>>
>> def OnSize(self, event):
>> if (not self.panel.minSizeSet):
>> self.panel.SetMinSize(wx.Size(20,20))
>> self.panel.minSizeSet = True
>>
>> self.SetStatusText(\"Size = %s\" % (self.panel.GetSize(),) )
>> event.Skip(True)
>>
>> So I want the panel to be a certain initial size, but I want to be able
>> to make it bigger or smaller afterwards.
>
>
>
> Hi James,
>
> One way is to set the frame to a default size and don\'t do the:
> self.SetSizerAndFit(box)

..SNIP CODE EXAMPLE..

This works OK, but then the panel isn't the right size because of the space
taken by the menu and status bar (and perhaps additional things in the future).

I really need the panel to be a certain size to start off with, but be able to
be resized bigger and *smaller* after the initial layout.

Thanks,
James

James Bigler

unread,
Jul 13, 2006, 2:51:01 AM7/13/06
to wxPytho...@lists.wxwidgets.org
> Hi James,
>
> Sorry, you should be able to set the size of the panel in the same way:
>

...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.

Thanks,
James

r...@raymondsmith.com

unread,
Jul 13, 2006, 5:02:52 AM7/13/06
to wxPytho...@lists.wxwidgets.org
Quoting James Bigler <big...@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?

The status bar is displayed as soon as the program starts on my PC\'s
(WinXP and Win2000 using Python 2.4 wxPython 2.6.3.2).

I have attached your program with my mods. Previously the inline
version was formatted poorly.

Regards,

Ray Smith

resize.py

James Bigler

unread,
Jul 13, 2006, 11:39:57 AM7/13/06
to wxPytho...@lists.wxwidgets.org
r...@raymondsmith.com wrote:
..SNIP..

> Hi James,
>
> I added:
> print \\\"Size = %s\\\" % self.panel.GetSize()
> and got the results:
> Size = (300, 400)
>
> did you get something else?

I got out that size, but wxPython doesn't size the panel in the window properly.
I've attached some images of what it looks like originally and after I resize
it a bit.

> The status bar is displayed as soon as the program starts on my PC\'s
> (WinXP and Win2000 using Python 2.4 wxPython 2.6.3.2).

I'm using Ubuntu 5.10 with Python 2.4.2, wxPython (GTK) 2.6.1.1. That's pretty
close to what you are using, so maybe this is a GTK issue?

> I have attached your program with my mods. Previously the inline
> version was formatted poorly.

I was able to run the files properly after I removed all the '\'s in front of
the quotes.

Thanks,
James

BTW, I really appreciate your help with this. I've been fighting this for days now.

resize1.png
resize2.png
resize3.png

r...@raymondsmith.com

unread,
Jul 13, 2006, 2:38:47 AM7/13/06
to wxPytho...@lists.wxwidgets.org
Quoting James Bigler <big...@cs.utah.edu>:

> This works OK, but then the panel isn\'t the right size because of the
> space taken by the menu and status bar (and perhaps additional things
> in the future).
>
> I really need the panel to be a certain size to start off with, but be
> able to be resized bigger and *smaller* after the initial layout.

Hi James,

Sorry, you should be able to set the size of the panel in the same way:

See code:

-------------
import wx

class MyApp(wx.App):
def OnInit(self):
frame = Frame(parent=None, title=\'Resize Panel\')
frame.Show()
self.SetTopWindow(frame)
return True

class Frame(wx.Frame):
def __init__(self, parent, title):

wx.Frame.__init__(self, parent=parent, title=title)

# Setup menu bar
menuBar = wx.MenuBar()
menu1 = wx.Menu()
self.Bind(wx.EVT_MENU, self.OnQuit, menu1.Append(wx.NewId(),
\"&Quit\"))
menuBar.Append(menu1, \"&File\")
menu2 = wx.Menu()
self.Bind(wx.EVT_MENU, self.OnAbout, menu2.Append(wx.NewId(),
\"About Me\"))
menuBar.Append(menu2, \"&Help\")
self.SetMenuBar(menuBar)

# Create status bar
self.CreateStatusBar()
self.SetStatusText(\"Welcome to wxPython!\")

# 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)

print \"Min Size = %s\" % self.panel.GetMinSize()
print \"Max Size = %s\" % self.panel.GetMaxSize()
print \"Best Size = %s\" % self.panel.GetBestSize()

print \"Size = %s\" % self.panel.GetSize()

def OnQuit(self, event):

Robin Dunn

unread,
Jul 13, 2006, 1:01:07 PM7/13/06
to wxPytho...@lists.wxwidgets.org
r...@raymondsmith.com wrote:
> Quoting James Bigler <big...@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.

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.


--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

resize.py

James Bigler

unread,
Jul 20, 2006, 1:06:40 PM7/20/06
to wxPytho...@lists.wxwidgets.org

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
Reply all
Reply to author
Forward
0 new messages