Panel's border obscures child windows

The code below shows 4 custom windows (in a GridBagSizer) placed on a
panel which is, in turn, placed on another panel (using a BoxSizer).
The latter panel is stretched to fill an entire 300x300 window.
My question: how do I make the panel containing the custom windows to
take into account its border (set with "style = wx.RAISED_BORDER"), so
that the border does not obscure the custom windows?

Code (just copy, paste and run to see the problem):

# -- CODE START --

import wx

class TestApp(wx.App):
    def OnInit(self):
        mainWin = MainWindow(None, -1, "untitled")
        self.SetTopWindow(mainWin)
        return True

class MainWindow(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size = (300, 300))
        
        mainPanel = wx.Panel(self)
        subPanel = wx.Panel(mainPanel, style = wx.RAISED_BORDER)
        mainSizer = wx.BoxSizer()
        subSizer = wx.GridBagSizer(hgap = 13, vgap = 13)
        
        mainSizer.Add(subPanel)
        subSizer.Add(CustomWindow(subPanel), wx.GBPosition(0, 0))
        subSizer.Add(CustomWindow(subPanel), wx.GBPosition(0, 1))
        subSizer.Add(CustomWindow(subPanel), wx.GBPosition(1, 0))
        subSizer.Add(CustomWindow(subPanel), wx.GBPosition(1, 1))
        
        subPanel.SetSizer(subSizer)
        mainPanel.SetSizer(mainSizer)
        
        self.Show(True)

class CustomWindow(wx.PyWindow):
    def __init__(self, parent):
        wx.PyWindow.__init__(self, parent, wx.ID_ANY, style =
wx.SIMPLE_BORDER, size = (50, 50))
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.SetBestFittingSize((50, 50))
        
    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        dc.Clear()
        dc.SetTextForeground(wx.Colour(0, 160, 0))
        text = "Custom"
        width, height = self.GetSize()
        textWidth, textHeight = dc.GetTextExtent(text)
        dc.DrawText(text, (width-textWidth)/2, (height-textHeight)/2)

    def DoGetBestSize(self):
        return (50, 50)

app = TestApp(0)
app.MainLoop()

# -- CODE END --

//Jonatan

Just want to clarify a little:
I know I could use the sizer's Add method's "border" and "flag"
properties. But this doesn't seem like a neat solution. And by the
way, -- if this is turns out to be the only way to get the panel's
border *not* to obscure the custom windows -- how do I detect the size
of the panel's border? This property could be platform/theme specific,
right?
I can't find a method to get the area occupied by a window's border.

//Jonatan

···

On Sun, 30 Jan 2005 18:52:52 +0100, Jonatan Johansson <jonatan.johansson@gmail.com> wrote:

The code below shows 4 custom windows (in a GridBagSizer) placed on a
panel which is, in turn, placed on another panel (using a BoxSizer).
The latter panel is stretched to fill an entire 300x300 window.
My question: how do I make the panel containing the custom windows to
take into account its border (set with "style = wx.RAISED_BORDER"), so
that the border does not obscure the custom windows?

Code (just copy, paste and run to see the problem):

# -- CODE START --

import wx

class TestApp(wx.App):
    def OnInit(self):
        mainWin = MainWindow(None, -1, "untitled")
        self.SetTopWindow(mainWin)
        return True

class MainWindow(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size = (300, 300))

        mainPanel = wx.Panel(self)
        subPanel = wx.Panel(mainPanel, style = wx.RAISED_BORDER)
        mainSizer = wx.BoxSizer()
        subSizer = wx.GridBagSizer(hgap = 13, vgap = 13)

        mainSizer.Add(subPanel)
        subSizer.Add(CustomWindow(subPanel), wx.GBPosition(0, 0))
        subSizer.Add(CustomWindow(subPanel), wx.GBPosition(0, 1))
        subSizer.Add(CustomWindow(subPanel), wx.GBPosition(1, 0))
        subSizer.Add(CustomWindow(subPanel), wx.GBPosition(1, 1))

        subPanel.SetSizer(subSizer)
        mainPanel.SetSizer(mainSizer)

        self.Show(True)

class CustomWindow(wx.PyWindow):
    def __init__(self, parent):
        wx.PyWindow.__init__(self, parent, wx.ID_ANY, style =
wx.SIMPLE_BORDER, size = (50, 50))
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.SetBestFittingSize((50, 50))

    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        dc.Clear()
        dc.SetTextForeground(wx.Colour(0, 160, 0))
        text = "Custom"
        width, height = self.GetSize()
        textWidth, textHeight = dc.GetTextExtent(text)
        dc.DrawText(text, (width-textWidth)/2, (height-textHeight)/2)

    def DoGetBestSize(self):
        return (50, 50)

app = TestApp(0)
app.MainLoop()

# -- CODE END --

//Jonatan

An extra Fit() call seems to do the trick, but I'm not sure why you need it after the Show() call:

class MainWindow(wx.Frame):
     def __init__(self, parent, id, title):
         wx.Frame.__init__(self, parent, id, title, size = (300, 300))

         mainPanel = wx.Panel(self)
         subPanel = wx.Panel(mainPanel, style = wx.RAISED_BORDER)
         mainSizer = wx.BoxSizer(wx.VERTICAL)
         subSizer = wx.GridBagSizer(hgap = 13, vgap = 13)

         mainSizer.Add(subPanel,0,wx.ALIGN_CENTER)
         subSizer.Add(CustomWindow(subPanel), wx.GBPosition(0, 0))
         subSizer.Add(CustomWindow(subPanel), wx.GBPosition(0, 1))
         subSizer.Add(CustomWindow(subPanel), wx.GBPosition(1, 0))
         subSizer.Add(CustomWindow(subPanel), wx.GBPosition(1, 1))

         subPanel.SetSizer(subSizer)
         mainPanel.SetSizer(mainSizer)
         self.Show(True)
         subPanel.Fit()

···

--
Christopher Barker, Ph.D.
Oceanographer
                                         
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Thanks Chris!

Fit seem to do the work (I looked at the Fit method of Sizers, but
overlooked the one of Windows. Doh!). But of course this raises some
more questions:

Q1: As you, Chris, mentioned: why does Fit have to be called after
Show (placing it just before the Show call doesn't help at all)?

Q2: Why isn't this adjustment caused by Fit happening automatically
when I call "subPanel.SetSizer(subSizer)"? I think that *not obscuring
child windows* should be default behaviour. Bug?

Q3: What is this "fuzziness-margin" mentioned in the manual (what is
the reason for the fuzziness in the first place?)?

The manual says this about Fit:

"if the window has exactly one subwindow it is better (faster and the
result is more precise as Fit adds some margin to account for
fuzziness of its calculations) to call

    window->SetClientSize(child->GetSize());

instead of calling Fit."

//Jonatan

···

On Mon, 31 Jan 2005 13:08:53 -0800, Chris Barker <Chris.Barker@noaa.gov> wrote:

An extra Fit() call seems to do the trick, but I'm not sure why you need
it after the Show() call:

class MainWindow(wx.Frame):
     def __init__(self, parent, id, title):
         wx.Frame.__init__(self, parent, id, title, size = (300, 300))

         mainPanel = wx.Panel(self)
         subPanel = wx.Panel(mainPanel, style = wx.RAISED_BORDER)
         mainSizer = wx.BoxSizer(wx.VERTICAL)
         subSizer = wx.GridBagSizer(hgap = 13, vgap = 13)

         mainSizer.Add(subPanel,0,wx.ALIGN_CENTER)
         subSizer.Add(CustomWindow(subPanel), wx.GBPosition(0, 0))
         subSizer.Add(CustomWindow(subPanel), wx.GBPosition(0, 1))
         subSizer.Add(CustomWindow(subPanel), wx.GBPosition(1, 0))
         subSizer.Add(CustomWindow(subPanel), wx.GBPosition(1, 1))

         subPanel.SetSizer(subSizer)
         mainPanel.SetSizer(mainSizer)
         self.Show(True)
         subPanel.Fit()

--
Christopher Barker, Ph.D.
Oceanographer

NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

Jonatan Johansson wrote:

Q1: As you, Chris, mentioned: why does Fit have to be called after
Show (placing it just before the Show call doesn't help at all)?

I'm guessing that Fit() doesn't work right until the inner windows have been shown, which may not happen until the Frame.Show() call. But that's just a guess...

Q2: Why isn't this adjustment caused by Fit happening automatically
when I call "subPanel.SetSizer(subSizer)"? I think that *not obscuring
child windows* should be default behaviour. Bug?

Perhaps the above?

Q3: What is this "fuzziness-margin" mentioned in the manual (what is
the reason for the fuzziness in the first place?)?

No idea on this one.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                         
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov