[wxPython] wxPanel/wxBoxSizer.Fit() bug?

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[wxPython] wxPanel/wxBoxSizer.Fit() bug?

John Lull
I'm writing a wxPython app.  Visually, I have a wxFrame containing a
single wxPanel, which contains a bunch of widgets inside a wxBoxSizer.
Sometimes, in response to user actions, I replace the wxPanel with a
new one containing totally different widgets, again inside a
wxBoxSizer.

I'm having 2 problems, both demonstrated by the sample code to follow.

1. I have to make the wxPanel __init__() method call the
wxBoxSizer.Fit() and .SetSizeHints() for both the wxPanel and wxFrame.
If I don't, I get various odd results, both in the sample code here
and in my real application. I haven't found any obvious way to make
the results propagate either way automatically.  I'm obviously missing
something here.

2. In the sample code below, when I press the 'Next' button after the
frame & panel have been automatically re-sized, the buttons apparently
grow by one pixel (watch the bottom and right edges of the 'Quit'
button when pressing 'Next').  If I have manually re-sized the frame
before pressing the 'Next' button, it behaves as I would expect.


I'm using Python 1.52, wxPython 2.1.13, and win32all 1.28, all on
Win98 SE.


Subsidiary questions:

1. Does it matter whether I call .Fit() or .SetSizeHints() first?

2. In an attempt to make .Fit() and .SetSizeHints() propagate, I
attempted to override several of the wxPanel methods.  My override
methods never get invoked.  Is there some way to tell from the
documentation which (if any) methods of any given class can be
overridden in Python?


Sample code follows:
# =========================================================

from wxPython.wx import *

ID_NEXT     = 1102
ID_EXIT     = 1103

# =========================================================
class TestPanel(wxPanel):
   def __init__(self, parent, frame, style):
      wxPanel.__init__(self, parent, -1, (-1,-1), (-1,-1),
                       style | wxTAB_TRAVERSAL)

      self.frame = frame

      nextButton = wxButton(self, ID_NEXT, 'Next')
      quitButton = wxButton(self, ID_EXIT, 'Quit')

      buttons = wxBoxSizer(wxHORIZONTAL)
      buttons.Add(nextButton, 1, wxEXPAND)
      buttons.Add(quitButton, 1, wxEXPAND)

      nextButton.SetFocus()

      self.SetAutoLayout(1)
      self.SetSizer(buttons)
      buttons.Fit(self)
      buttons.SetSizeHints(self)
      buttons.Fit(parent)
      buttons.SetSizeHints(parent)

# =========================================================
class TestFrame(wxFrame):
   def __init__(self, parent, ID, title):
      wxFrame.__init__(self, parent, ID, title,
                       wxDefaultPosition, wxSize(350, 450))

      EVT_BUTTON(self, ID_NEXT,     self.OnNext)
      EVT_BUTTON(self, ID_EXIT,     self.OnExit)

      self.panel = TestPanel(self, self, wxSTATIC_BORDER)

   # ------------------- Event handlers -------------------
   def OnNext(self, event):
      self.panel.Destroy()
      self.panel = TestPanel(self, self, wxSTATIC_BORDER)

   def OnExit(self, event):
      self.Destroy()

# =========================================================
class TestApp(wxApp):
   def OnInit(self):
      frame = TestFrame(NULL, -1, "Test")
      frame.Iconize(0)
      frame.Show(true)
      self.SetTopWindow(frame)
      return true

# =========================================================
if __name__ == "__main__":
   app = TestApp(0)
   app.MainLoop()


_______________________________________________
wxPython-users maillist  -  [hidden email]
http://starship.python.net/mailman/listinfo/wxpython-users



Reply | Threaded
Open this post in threaded view
|

Re: [wxPython] wxPanel/wxBoxSizer.Fit() bug?

Robin Dunn

> 1. I have to make the wxPanel __init__() method call the
> wxBoxSizer.Fit() and .SetSizeHints() for both the wxPanel and wxFrame.
> If I don't, I get various odd results, both in the sample code here
> and in my real application. I haven't found any obvious way to make
> the results propagate either way automatically.  I'm obviously missing
> something here.

When you call Fit() for the panel it sets it's current size to the default of
the sizer, but since it is the only child of the frame the frame will resize
it to fill the client area.  That is why you needed  to call fit for the
frame too.  Probably a better solution would be to do something like the
following:

      buttons.Fit(self)
      frame.SetClientSize(self.GetSize())

This also takes care of your second problem too.

On the other hand, SetSizeHints really only makes sense on frames or other
windows that can be resized by the user or the window manager.  So if you
want to restrict the size of the frame to match the above, then you only need
to do it for the frame.  This would be a good way to do it:

      width, height = frame.GetSizeTuple()
      frame.SetSizeHints(width, height, width, height)


> 2. In an attempt to make .Fit() and .SetSizeHints() propagate, I
> attempted to override several of the wxPanel methods.  My override
> methods never get invoked.  Is there some way to tell from the
> documentation which (if any) methods of any given class can be
> overridden in Python?

Making virtual methods in C++ propogate to Python is fairly expensive, both
in runtime efficiency as well as the amount of code needed.  For that reason
the vast majority of the methods are one-way (Python --> c++)  Only those
methods that must be or should be overridden in derived classes to provide
needed functionality support doing it.  I've tried to ensure that doc entries
where it is supported will say things like "this method should be overridden
in derived classes" or something to that effect, but some have undoubtedly
slipped through the cracks.

--
Robin Dunn
Software Craftsman
[hidden email]
http://AllDunn.com/robin/
http://AllDunn.com/wxPython/  Check it out!



_______________________________________________
wxPython-users maillist  -  [hidden email]
http://starship.python.net/mailman/listinfo/wxpython-users