Discussion:
Showing and hiding panels
Aaron MacDonald
2008-01-27 00:23:07 UTC
Permalink
Hi,

My application requires several states such that only one state is
shown at a time in a single window (frame). I intend to represent
each state as a subclass of Panel, each with their own set of
controls. Only one of these panels should be visible at a time. The
frame should be sized such that it fits the largest panel, and any
smaller panels should be resized to fit the frame. Basically, I want
something like CardLayout from Java Swing.

I've had a look at the Show() and Hide() methods of window objects,
but I'm not sure what structure I need to fit these different panels
in a frame, how to properly show and hide panels, and how to properly
resize any panels that are too small. Has anyone else done something
like this?

Thank you,

Aaron M.
C M
2008-01-27 04:58:55 UTC
Permalink
Post by Aaron MacDonald
Hi,
My application requires several states such that only one state is
shown at a time in a single window (frame). I intend to represent
each state as a subclass of Panel, each with their own set of
controls. Only one of these panels should be visible at a time. The
frame should be sized such that it fits the largest panel, and any
smaller panels should be resized to fit the frame. Basically, I want
something like CardLayout from Java Swing.
I've had a look at the Show() and Hide() methods of window objects,
but I'm not sure what structure I need to fit these different panels
in a frame, how to properly show and hide panels, and how to properly
resize any panels that are too small. Has anyone else done something
like this?
Thank you,
Aaron M.
I haven't seen CardLayout from Java Swing, but have you looked at the
wxPython demo for the various "book" controls? (notebook, toolbook,
listbook, etc.)?

I'm not sure what you mean by properly show and hide panels. Or to properly
resize panels that are too small...are you using sizers and also setting
minimum sizes for your panels?
Aaron MacDonald
2008-01-27 15:47:38 UTC
Permalink
I took a look at the Notebook control and related controls. It's sort
of what I want, except that I don't want the tab buttons on the top.
I want panel (tab) switching to be done by the currently active panel.

This is a game I'm working on. So, I'd want to first present the
title screen to the player, which would have the logo and buttons for
starting a new game or quitting. The player clicks on the start
button, which makes the interface switch to the main game screen. As
the player interacts with the game, he may access other screens like
ones displaying his status or what items he has collected. If the
player wins or looses, the interface switches to the game-won or game-
over screen, which would again switch back to the title screen when
the player hits a key. Each of these screens I want to be able to
represent as a panel, and the outer frame should have some kind of
stack of these panels where it can present one to the player at any
moment.

As for resizing panels, I mean that some of my panels would have
controls with a fixed size. I think therefore that some panels would
end up being bigger than others due to what controls are in them. I
want the outer frame to have a single size, so I think some panels end
up needing their contents stretched somehow.

Thanks,

Aaron M.
Post by Aaron MacDonald
Hi,
My application requires several states such that only one state is
shown at a time in a single window (frame). I intend to represent
each state as a subclass of Panel, each with their own set of
controls. Only one of these panels should be visible at a time. The
frame should be sized such that it fits the largest panel, and any
smaller panels should be resized to fit the frame. Basically, I want
something like CardLayout from Java Swing.
I've had a look at the Show() and Hide() methods of window objects,
but I'm not sure what structure I need to fit these different panels
in a frame, how to properly show and hide panels, and how to properly
resize any panels that are too small. Has anyone else done something
like this?
Thank you,
Aaron M.
I haven't seen CardLayout from Java Swing, but have you looked at
the wxPython demo for the various "book" controls? (notebook,
toolbook, listbook, etc.)?
I'm not sure what you mean by properly show and hide panels. Or to
properly resize panels that are too small...are you using sizers and
also setting minimum sizes for your panels?
C M
2008-01-27 17:04:01 UTC
Permalink
Post by Aaron MacDonald
I took a look at the Notebook control and related controls. It's sort
of what I want, except that I don't want the tab buttons on the top.
I want panel (tab) switching to be done by the currently active panel.
This is a game I'm working on. So, I'd want to first present the
title screen to the player, which would have the logo and buttons for
starting a new game or quitting. The player clicks on the start
button, which makes the interface switch to the main game screen. As
the player interacts with the game, he may access other screens like
ones displaying his status or what items he has collected. If the
player wins or looses, the interface switches to the game-won or game-
over screen, which would again switch back to the title screen when
the player hits a key. Each of these screens I want to be able to
represent as a panel, and the outer frame should have some kind of
stack of these panels where it can present one to the player at any
moment.
As for resizing panels, I mean that some of my panels would have
controls with a fixed size. I think therefore that some panels would
end up being bigger than others due to what controls are in them. I
want the outer frame to have a single size, so I think some panels end
up needing their contents stretched somehow.
Thanks,
Aaron M.
Ok, that makes it much clearer for me to picture. What you are describing
should not be too tough at all.

Basically what you could do is create all your panels and manage the size of
the controls within them using sizers, like BoxSizer or whatever. If you
are new to sizers, there is some tutorials out there on that, or you could
try them or fool around with them in the demo, or ask questions, etc. But
sizers will allow you have have "their contents stretched somehow" very
nicely.

You then would start off (on init) by hiding all but the title screen. You
would then put the appropriate Hide() and Show() commands linked to event
handlers on particular controls, meaning if you pressed a button it would
show the appropriate panel and hide the others. As I understand it, Hide()
and Show() work well with sizers in that the sizer takes into account only
panels which are shown--that's a big help in this.

There are probably more clever ways of handling multiple panels in this way
(that is what Notebook tries to simplify, but I understand that is not part
of the game standard look), but if you just start with two panels and use
sizers and then try switching between them, it should become more intuitive
to you.
Aaron MacDonald
2008-01-27 18:49:32 UTC
Permalink
O.K. I've done an experiment here to see how I'll do this.

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

sizer = wx.BoxSizer()
self.SetSizer(sizer)

self.panel1 = SomePanel(self)
self.panel2 = AnotherPanel(self)

sizer.Add(self. panel1, 1, flag = wx.EXPAND)
sizer.Add(self. panel2, 1, flag = wx.EXPAND)

self. panel2.Hide()

sizer.Fit(self)
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPress)

self.toggle = False

def OnKeyPress(self, event):
self.toggle = not self.toggle

if self.toggle:
self. panel1.Hide()
self. panel2.Show()
else:
self. panel2.Hide()
self. panel1.Show()

event.Skip()

Right now the sub-panels don't have any active controls, so the frame
itself is collecting the events. The first panel only has a button on
it. The second panel has a custom control in it which has a set
minimum size which is larger than the button on the first panel, so
the second panel would be bigger than the first panel. I want my
frame to be the size of the second (larger) panel, though I only show
the first panel on startup. Both panels have a sizer to which I've
added their controls to.

There are two problems with this. First, the frame is the size of the
first panel on startup instead of the size of the second panel.
Secondly, when I switch panels the new panel is only properly redrawn
when I manually resize the frame.
Post by C M
Ok, that makes it much clearer for me to picture. What you are
describing should not be too tough at all.
Basically what you could do is create all your panels and manage the
size of the controls within them using sizers, like BoxSizer or
whatever. If you are new to sizers, there is some tutorials out
there on that, or you could try them or fool around with them in the
demo, or ask questions, etc. But sizers will allow you have have
"their contents stretched somehow" very nicely.
You then would start off (on init) by hiding all but the title
screen. You would then put the appropriate Hide() and Show()
commands linked to event handlers on particular controls, meaning if
you pressed a button it would show the appropriate panel and hide
the others. As I understand it, Hide() and Show() work well with
sizers in that the sizer takes into account only panels which are
shown--that's a big help in this.
There are probably more clever ways of handling multiple panels in
this way (that is what Notebook tries to simplify, but I understand
that is not part of the game standard look), but if you just start
with two panels and use sizers and then try switching between them,
it should become more intuitive to you.
C M
2008-01-27 20:02:42 UTC
Permalink
Post by Aaron MacDonald
O.K. I've done an experiment here to see how I'll do this.
wx.Frame.__init__(self, parent, id, title)
sizer = wx.BoxSizer()
self.SetSizer(sizer)
self.panel1 = SomePanel(self)
self.panel2 = AnotherPanel(self)
sizer.Add(self. panel1, 1, flag = wx.EXPAND)
sizer.Add(self. panel2, 1, flag = wx.EXPAND)
self. panel2.Hide()
sizer.Fit(self)
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPress)
self.toggle = False
self.toggle = not self.toggle
self. panel1.Hide()
self. panel2.Show()
self. panel2.Hide()
self. panel1.Show()
event.Skip()
Right now the sub-panels don't have any active controls, so the frame
itself is collecting the events. The first panel only has a button on
it. The second panel has a custom control in it which has a set
minimum size which is larger than the button on the first panel, so
the second panel would be bigger than the first panel. I want my
frame to be the size of the second (larger) panel, though I only show
the first panel on startup. Both panels have a sizer to which I've
added their controls to.
There are two problems with this. First, the frame is the size of the
first panel on startup instead of the size of the second panel.
Secondly, when I switch panels the new panel is only properly redrawn
when I manually resize the frame.
It's always best to attach small runnable samples when asking; what you have
attached does not correspond to what you are describing, and its not
runnable.

I think you can set the size of the frame to be equal to the size of the 2nd
panel (here "self" refers to the frame):

framesize = second_panel.GetSize()
self.SetClientSize(framesize)

Then, when you do your switching of panels, you want to call Layout() to
make sure things are properly redrawn. I am often unclear myself which
control or sizer ought to be the one that I call Layout() on, but try it on
the shown panel, such as

second_panel.Layout()
if not, try it on the frame itself, as in self.Layout()
Post by Aaron MacDonald
Post by C M
Ok, that makes it much clearer for me to picture. What you are
describing should not be too tough at all.
Basically what you could do is create all your panels and manage the
size of the controls within them using sizers, like BoxSizer or
whatever. If you are new to sizers, there is some tutorials out
there on that, or you could try them or fool around with them in the
demo, or ask questions, etc. But sizers will allow you have have
"their contents stretched somehow" very nicely.
You then would start off (on init) by hiding all but the title
screen. You would then put the appropriate Hide() and Show()
commands linked to event handlers on particular controls, meaning if
you pressed a button it would show the appropriate panel and hide
the others. As I understand it, Hide() and Show() work well with
sizers in that the sizer takes into account only panels which are
shown--that's a big help in this.
There are probably more clever ways of handling multiple panels in
this way (that is what Notebook tries to simplify, but I understand
that is not part of the game standard look), but if you just start
with two panels and use sizers and then try switching between them,
it should become more intuitive to you.
---------------------------------------------------------------------
Loading...