Another layout problem

Hello,

I'm trying to build a frame with some progress information. The layout is like:
Frame
    main_sizer(BoxSizer)
       panel
          table_sizer(BoxSizer)
                activeProcess(StaticText)
                gauge(Gauge)
                start(StaticText)
                end(StaticText)
                grid_main_sizer(GridSizer)
                      table_col_1(StaticText)
                      ....

and a function 'make process' that adds a row in the grid_main_sizer. After running the function the layout is not refreshed correctly. The hight of the frame is not resized.
I put some print statements into the code (see below). Resizing of the grid_main_sizer and table_sizer seems to work but everything above don't resize:
sizer before (GetMinSize) after (GetMinSize)
gridsizer (76,13) (76,26)
table_sizer (250,77) (250,90)
main_sizer (250,77) (250,77)
frame (258,104) (258,104)

It should be something obvious but I can't get it. Any hints ? (Win XP, py 2.4.2, wxpy 2.6.2.1)

regards,
Jürgen

code:
#!/usr/bin/env python
# -*- coding: ISO-8859-1 -*-

import wx,time

class MyGaugeFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.panel = wx.Panel(self, -1)
        self.SetTitle("Test Gauge")
               # table definition
        self.cols=4
        self.lastnum=5
               self.active_process=wx.StaticText(self.panel, -1, "", (45, 15))
        self.start=wx.StaticText(self.panel, -1, "Beginn:", (45, 15))
        self.end=wx.StaticText(self.panel, -1, "End:", (45, 15))
        self.gauge= wx.Gauge(self.panel, -1, 50, (110, 50), (250, 25),wx.GA_SMOOTH)
               #Columns
        self.table_col_1=wx.StaticText(self.panel, -1, "col1", (45, 15))
        self.table_col_2=wx.StaticText(self.panel, -1, "col2", (45, 15))
        self.table_col_3=wx.StaticText(self.panel, -1, "col3", (45, 15))
        self.table_col_4=wx.StaticText(self.panel, -1, "col4", (45, 15))
       
         self.__do_layout()
        self.make_prozess('test')

    def __do_layout(self):
        #def sizer
        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
        self.table_sizer = wx.BoxSizer(wx.VERTICAL)
        self.grid_main_sizer = wx.GridSizer(4, 4, 0, 0)
               #set sizers
        self.table_sizer.Add(self.active_process, 0, wx.EXPAND, 0)
        self.table_sizer.Add(self.gauge, 0, wx.EXPAND, 0)
        self.table_sizer.Add(self.start, 0, wx.EXPAND, 0)
        self.table_sizer.Add(self.end, 0, wx.EXPAND, 0)
        self.table_sizer.Add(self.grid_main_sizer, 10, wx.EXPAND, 0)
        #Columns
        self.grid_main_sizer.Add(self.table_col_1, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
        self.grid_main_sizer.Add(self.table_col_2, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
        self.grid_main_sizer.Add(self.table_col_3, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
        self.grid_main_sizer.Add(self.table_col_4, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
       
               #layout sizers
        self.grid_main_sizer.SetSizeHints(self.panel)
        self.panel.SetAutoLayout(True)
        self.panel.SetSizer(self.table_sizer)
        self.table_sizer.Fit(self.panel)
        self.table_sizer.SetSizeHints(self.panel)
        self.main_sizer.Add(self.panel, 1, wx.EXPAND, 0)
        self.SetAutoLayout(True)
        self.SetSizer(self.main_sizer)
        self.main_sizer.Fit(self)
        self.main_sizer.SetSizeHints(self)
        self.Layout()
       
    def make_prozess(self,name):
        print 'before',self.grid_main_sizer.GetMinSize(),self.table_sizer.GetMinSize(),self.main_sizer.GetMinSize(),self.GetMinSize()
        for item in range(self.lastnum,self.lastnum+self.cols):
            exec('self.table_col_'+str(item)+'=wx.StaticText(self.panel, -1, "Hi", (45, 15))')
            self.grid_main_sizer.Add(eval('self.table_col_'+str(item)), 1, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
        self.lastnum=self.lastnum+self.cols
        self.active_process.SetLabel('Running: '+name)
               self.grid_main_sizer.Fit(self.panel)
        self.grid_main_sizer.Layout()
        print 'after',self.grid_main_sizer.GetMinSize(),
               self.table_sizer.Fit(self.panel),
        self.table_sizer.Layout()
        print self.table_sizer.GetMinSize(),
               self.main_sizer.SetSizeHints(self)
        self.main_sizer.Layout()
        print self.main_sizer.GetMinSize(),
               self.Fit()
        self.Layout()
        print self.GetMinSize()

if __name__ == "__main__":
    app = wx.PySimpleApp(0)
    wx.InitAllImageHandlers()
    frame_1 = MyGaugeFrame(None, -1, "")
    app.SetTopWindow(frame_1)
    frame_1.Show()
    app.MainLoop()

Jürgen Kareta wrote:

Hello,

I'm trying to build a frame with some progress information. The layout is like:
Frame
   main_sizer(BoxSizer)
      panel
         table_sizer(BoxSizer)
               activeProcess(StaticText)
               gauge(Gauge)
               start(StaticText)
               end(StaticText)
               grid_main_sizer(GridSizer)
                     table_col_1(StaticText)
                     ....

and a function 'make process' that adds a row in the grid_main_sizer. After running the function the layout is not refreshed correctly. The hight of the frame is not resized.

This is a common ailment that has come to be known as overwhelmussizeritus. Fortunately the cure is easy, there is not even any need for a trip to the pharmacy! Just a bit of surgical use of the delete key. :wink:

See attached for the lines that I commented out. The main issue is all of the uses of the sizer.SetSizeHints method. This sets the minsize of the window to be the size needed by the sizer, but for windows that have sizers that is pretty much the default behavior anyway, but setting the minsize overrides what the sizer would report as the needed size and so when changes are being made it becomes less flexible. The only time that SetSizeHints is really needed is for top-level windows in order to ensure that the user does not make them shrink too small.

The other surgical removals were not all necessary to bring this patient back to correct functionality, but they were redundant so I removed them as well. The window.SetAutoLayout is automatically called when window.SetSizer is called, so it is not needed unless you want to turn off AutoLayout for some reason. The Fit methods (window and sizer) essentially duplicate what normally happens when a layout is done on a window with a sizer, so since the top-level window is getting resized we can expect that the component windows will also be getting resized and so their Layout methods will automatically be called in their default EVT_SIZE event handler, so the extra Fit's and Layout's are redundant.

layout4.py (3.76 KB)

···

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

Hello Robin,

thanks a lot for your effort and explanations. I often spend a lot of time to solve unexpected optical behavior in my scripts. Starting with a template of wxglade most of the relevant instructions in this script where added after searching the archiv for similar problems and adapting the solutions. However most of them seems to be outdated.

Maybe a workflow similar to the one for the event handling in the python in action book would be really usefull (I got the book a few days ago, so I'm still reading). I'll think about it again after finish reading.

Jürgen

···

Jürgen Kareta wrote:

Hello,

I'm trying to build a frame with some progress information. The layout is like:
Frame
   main_sizer(BoxSizer)
      panel
         table_sizer(BoxSizer)
               activeProcess(StaticText)
               gauge(Gauge)
               start(StaticText)
               end(StaticText)
               grid_main_sizer(GridSizer)
                     table_col_1(StaticText)
                     ....

and a function 'make process' that adds a row in the grid_main_sizer. After running the function the layout is not refreshed correctly. The hight of the frame is not resized.

This is a common ailment that has come to be known as overwhelmussizeritus. Fortunately the cure is easy, there is not even any need for a trip to the pharmacy! Just a bit of surgical use of the delete key. :wink:

See attached for the lines that I commented out. The main issue is all of the uses of the sizer.SetSizeHints method. This sets the minsize of the window to be the size needed by the sizer, but for windows that have sizers that is pretty much the default behavior anyway, but setting the minsize overrides what the sizer would report as the needed size and so when changes are being made it becomes less flexible. The only time that SetSizeHints is really needed is for top-level windows in order to ensure that the user does not make them shrink too small.

The other surgical removals were not all necessary to bring this patient back to correct functionality, but they were redundant so I removed them as well. The window.SetAutoLayout is automatically called when window.SetSizer is called, so it is not needed unless you want to turn off AutoLayout for some reason. The Fit methods (window and sizer) essentially duplicate what normally happens when a layout is done on a window with a sizer, so since the top-level window is getting resized we can expect that the component windows will also be getting resized and so their Layout methods will automatically be called in their default EVT_SIZE event handler, so the extra Fit's and Layout's are redundant.

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

#!/usr/bin/env python
# -*- coding: ISO-8859-1 -*-

import wx,time

class MyGaugeFrame(wx.Frame):
  def __init__(self, *args, **kwds):
      kwds["style"] = wx.DEFAULT_FRAME_STYLE
      wx.Frame.__init__(self, *args, **kwds)
      self.panel = wx.Panel(self, -1)
      self.SetTitle("Test Gauge")
      # table definition
      self.cols=4
      self.lastnum=5
      self.active_process=wx.StaticText(self.panel, -1, "", (45, 15))
      self.start=wx.StaticText(self.panel, -1, "Beginn:", (45, 15))
      self.end=wx.StaticText(self.panel, -1, "End:", (45, 15))
      self.gauge= wx.Gauge(self.panel, -1, 50, (110, 50), (250, 25),wx.GA_SMOOTH)
      #Columns
      self.table_col_1=wx.StaticText(self.panel, -1, "col1", (45, 15))
      self.table_col_2=wx.StaticText(self.panel, -1, "col2", (45, 15))
      self.table_col_3=wx.StaticText(self.panel, -1, "col3", (45, 15))
      self.table_col_4=wx.StaticText(self.panel, -1, "col4", (45, 15))
          self.__do_layout()
      self.make_prozess('test1')
      wx.FutureCall(1000, self.make_prozess, 'test2')
      wx.FutureCall(2000, self.make_prozess, 'test3')
      wx.FutureCall(3000, self.make_prozess, 'test4')
      wx.FutureCall(4000, self.make_prozess, 'test5')

  def __do_layout(self):
      #def sizer
      self.main_sizer = wx.BoxSizer(wx.VERTICAL)
      self.table_sizer = wx.BoxSizer(wx.VERTICAL)
      self.grid_main_sizer = wx.GridSizer(4, 4, 0, 0)
      #set sizers
      self.table_sizer.Add(self.active_process, 0, wx.EXPAND, 0)
      self.table_sizer.Add(self.gauge, 0, wx.EXPAND, 0)
      self.table_sizer.Add(self.start, 0, wx.EXPAND, 0)
      self.table_sizer.Add(self.end, 0, wx.EXPAND, 0)
      self.table_sizer.Add(self.grid_main_sizer, 10, wx.EXPAND, 0)
      #Columns
      self.grid_main_sizer.Add(self.table_col_1, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
      self.grid_main_sizer.Add(self.table_col_2, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
      self.grid_main_sizer.Add(self.table_col_3, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
      self.grid_main_sizer.Add(self.table_col_4, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
          #layout sizers
      #self.grid_main_sizer.SetSizeHints(self.panel)
      #self.panel.SetAutoLayout(True)
      self.panel.SetSizer(self.table_sizer)
      #self.table_sizer.Fit(self.panel)
      #self.table_sizer.SetSizeHints(self.panel)
      self.main_sizer.Add(self.panel, 1, wx.EXPAND, 0)
      #self.SetAutoLayout(True)
      self.SetSizer(self.main_sizer)
      #self.main_sizer.Fit(self)
      #self.main_sizer.SetSizeHints(self)
      #self.Layout()
    
  def make_prozess(self,name):
      print 'before',self.grid_main_sizer.GetMinSize(),self.table_sizer.GetMinSize(),self.main_sizer.GetMinSize(),self.GetMinSize()
      for item in range(self.lastnum,self.lastnum+self.cols):
          exec('self.table_col_'+str(item)+'=wx.StaticText(self.panel, -1, "Hi", (45, 15))')
          self.grid_main_sizer.Add(eval('self.table_col_'+str(item)), 1, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
      self.lastnum=self.lastnum+self.cols
      self.active_process.SetLabel('Running: '+name)
            #self.grid_main_sizer.Fit(self.panel)
      #self.grid_main_sizer.Layout()
      print 'after',self.grid_main_sizer.GetMinSize(),
      #self.table_sizer.Fit(self.panel),
      #self.table_sizer.Layout()
      print self.table_sizer.GetMinSize(),
      self.main_sizer.SetSizeHints(self)
      #self.main_sizer.Layout()
      print self.main_sizer.GetMinSize(),
      #self.Fit()
      #self.Layout()
      print self.GetMinSize()

if __name__ == "__main__":
  app = wx.PySimpleApp(0)
  wx.InitAllImageHandlers()
  frame_1 = MyGaugeFrame(None, -1, "")
  app.SetTopWindow(frame_1)
  frame_1.Show()
  app.MainLoop()

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

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