Setting the initial vs. SetMinSize vs. SetSize

I am trying to set a minimum size for a grid, as well as a larger
initial size for that object, but in the code below SetMinSize seems
to set both and SetSize appears to be ignored. The only thing I have
found that allows me to achieve my intended result is to replace
sizer.Fit(self) with self.SetSize(...), but this is not exactly what I
had wanted to do.

I am trying to understand how wxPython implements sizers so I would
like to understand why this code does not work as I would have
expected -- what SetSize actually does in this context --- and/or
should I be using a different approach?

Brian

import wx, wx.grid

class GridDialog(wx.Dialog):
    def __init__(self, parent):
        style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER
        wx.Dialog.__init__(self, parent, wx.ID_ANY,
                           "window title", style=style)
        sizer = wx.BoxSizer(wx.VERTICAL)
        label = wx.StaticText(self, wx.ID_ANY, 'grid label')
        sizer.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.grid = EditGrid(self)
        sizer.Add(self.grid, 1,
                  wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
        line = wx.StaticLine(self, wx.ID_ANY,
                             style=wx.LI_HORIZONTAL)
        sizer.Add(line, 0, wx.GROW|wx.TOP, 5)
        btnsizer = wx.StdDialogButtonSizer()
        btn = wx.Button(self, wx.ID_OK)
        btnsizer.AddButton(btn)
        btnsizer.Realize()
        sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
        self.SetSizer(sizer)
        sizer.Fit(self)

class EditGrid(wx.grid.Grid):
    def __init__(self, panel):
        wx.grid.Grid.__init__(self, panel, wx.ID_ANY)
        self.SetMinSize((200,200))
        self.SetSize((400,400))
        self.rows,self.cols = 10,12
        self.CreateGrid(self.rows, self.cols)
        self.SetRowLabelSize(30)
        for c in range(self.cols):
            self.SetColSize(c, 50)
            for r in range(self.rows):
                self.SetCellValue(r, c, "%d-%d" % (c+1,r+1))

class myframe(wx.Frame):
  def __init__(self):
    wx.Frame.__init__(self, None)
    pnl = wx.Panel(self)
    sizer = wx.BoxSizer(wx.VERTICAL)
    pnl.SetSizer(sizer)
    btn = wx.Button(pnl, wx.ID_ANY, "Open Grid")
    btn.Bind(wx.EVT_BUTTON, self.OnClick)
    sizer.Add(btn,0,wx.ALL,10)
    sizer.Fit(self)
    self.Show()

  def OnClick(self, event):
    dlg = GridDialog(self)
    val = dlg.ShowModal()
    dlg.Destroy()
    return

if __name__ == "__main__":
    app = wx.PySimpleApp() # create the App
    frm = myframe()
    app.MainLoop()

SetSize does nothing but set the size of the window, it has almost no influence on the sizer's layout algorithm. The sizers will call the window's GetEffectiveMinSize method to determine what are the basic needs of the window that the sizer should honor. The effective minsize is basically the window's best size that has been overridden by the minsize if it has been set. The implementation is shown below. The best size is determined by each type of widget and is usually based on the content of the widget in some way. The minsize is how the programmer can override all or part of that value. The sizer takes the effective minsize and sets the widget to that size, unless it has been told to expand the item in some way and there is extra space available.

wxSize wxWindowBase::GetEffectiveMinSize() const
{
     // merge the best size with the min size, giving priority to the min size
     wxSize min = GetMinSize();

     if (min.x == wxDefaultCoord || min.y == wxDefaultCoord)
     {
         wxSize best = GetBestSize();
         if (min.x == wxDefaultCoord) min.x = best.x;
         if (min.y == wxDefaultCoord) min.y = best.y;
     }

     return min;
}

···

On 11/10/11 3:40 PM, bht wrote:

I am trying to set a minimum size for a grid, as well as a larger
initial size for that object, but in the code below SetMinSize seems
to set both and SetSize appears to be ignored. The only thing I have
found that allows me to achieve my intended result is to replace
sizer.Fit(self) with self.SetSize(...), but this is not exactly what I
had wanted to do.

I am trying to understand how wxPython implements sizers so I would
like to understand why this code does not work as I would have
expected -- what SetSize actually does in this context

--
Robin Dunn
Software Craftsman

Just use SetInitialSize instead of SetSize.

self.SetMinSize((900, 800))
self.SetInitialSize((1600, 1000))
self.Fit()
self.CenterOnScreen()
···

On Friday, 11 November 2011 00:40:33 UTC+1, bht wrote:

I am trying to set a minimum size for a grid, as well as a larger

initial size for that object, but in the code below SetMinSize seems

to set both and SetSize appears to be ignored. The only thing I have

found that allows me to achieve my intended result is to replace

sizer.Fit(self) with self.SetSize(…), but this is not exactly what I

had wanted to do.

I am trying to understand how wxPython implements sizers so I would

like to understand why this code does not work as I would have

expected – what SetSize actually does in this context — and/or

should I be using a different approach?

Brian

import wx, wx.grid

class GridDialog(wx.Dialog):

def __init__(self, parent):

    style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER

    wx.Dialog.__init__(self, parent, wx.ID_ANY,

                       "window title", style=style)

    sizer = wx.BoxSizer(wx.VERTICAL)

    label = wx.StaticText(self,  wx.ID_ANY, 'grid label')

    sizer.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)

    self.grid = EditGrid(self)

    sizer.Add(self.grid, 1,

              wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)

    line = wx.StaticLine(self,  wx.ID_ANY,

                         style=wx.LI_HORIZONTAL)

    sizer.Add(line, 0, wx.GROW|wx.TOP, 5)

    btnsizer = wx.StdDialogButtonSizer()

    btn = wx.Button(self, wx.ID_OK)

    btnsizer.AddButton(btn)

    btnsizer.Realize()

    sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)

    self.SetSizer(sizer)

    sizer.Fit(self)

class EditGrid(wx.grid.Grid):

def __init__(self, panel):

    wx.grid.Grid.__init__(self, panel,  wx.ID_ANY)

    self.SetMinSize((200,200))

    self.SetSize((400,400))

    self.rows,self.cols = 10,12

    self.CreateGrid(self.rows, self.cols)

    self.SetRowLabelSize(30)

    for c in range(self.cols):

        self.SetColSize(c, 50)

        for r in range(self.rows):

            self.SetCellValue(r, c, "%d-%d" % (c+1,r+1))

class myframe(wx.Frame):

def init(self):

wx.Frame.__init__(self, None)

pnl = wx.Panel(self)

sizer = wx.BoxSizer(wx.VERTICAL)

pnl.SetSizer(sizer)

btn = wx.Button(pnl, wx.ID_ANY, "Open Grid")

btn.Bind(wx.EVT_BUTTON, self.OnClick)

sizer.Add(btn,0,wx.ALL,10)

sizer.Fit(self)

self.Show()

def OnClick(self, event):

dlg = GridDialog(self)

val = dlg.ShowModal()

dlg.Destroy()

return

if name == “main”:

app = wx.PySimpleApp() # create the App

frm = myframe()

app.MainLoop()