problem with overlapping and truncated buttons

I'm generating a panel containing several buttons. For reasons that I don't
understand, the buttons overlap one another and/or are truncated by the edge of
the panel. Any suggestions will be appreciated.

Phillip

import wx
from wx.lib.agw.aquabutton import AquaButton
from numpy import ceil
button_font_point_size= 16

class DocPanel(wx.Panel):

   def __init__(self, parent, bgcolor=wx.Colour(250, 250, 250)):
      wx.Panel.__init__(self,parent)
      self.SetBackgroundColour(bgcolor)
      self.Buttons= []
      self.sizer= None

   def GetDocs(self):
      return ['ABCDEFGHIJKLMNOP','QRSTUVWXYZ','123456789','Z9Y8X7W6V5U4T3S2R1Q0']

   def Populate(self):
      # If this is the first call to `Populate` then the panel has no contents
      # and self.sizer still holds the default None value
      if self.sizer is not None:
         for indx in xrange(len(self.Buttons)-1,-1,-1):
            button= self.Buttons.pop(indx)
            self.sizer.RemoveWindow(button)
            button.Destroy()

      stringList= self.GetDocs()

      # Create new sizer
      total_docs= len(stringList)
      flex_rows= int(ceil(total_docs/2.0))
      flex_cols= 2 if total_docs>=2 else 1
      self.sizer= wx.FlexGridSizer(rows=flex_rows, cols=flex_cols)
      self.SetSizer(self.sizer)

      for name in stringList:
         button= AquaButton(self, id=-1, label=name)
         self.ButtonEnable(button)
         self.Buttons.append(button)
         self.sizer.Add(button,0,wx.ALL|wx.ALIGN_CENTER,6)

      self.Layout()
      self.GetParent().Fit()
      self.GetTopLevelParent().Fit()
      self.GetTopLevelParent().Refresh()

   def ButtonEnable(self, button):
      """
      Enable User Manual or Changes Button.
      """
      button_font= wx.Font(button_font_point_size, wx.SWISS, wx.NORMAL,
         wx.FONTWEIGHT_BOLD)
      button.Enable()
      button.SetFont(button_font)
      button.SetToolTip(wx.ToolTip("This button does something."))
      button._backColour= wx.Colour(147, 202, 255)
      button._hoverColour= button.LightColour(button._backColour, 30)
      button._textColour= wx.BLACK
      button.Refresh()

   def ButtonDisable(self, button):
      """
      Disable User Manual or Changes Button.
      """
      button.Disable()
      button._backColour= wx.Colour(200, 200, 200)
      button._hoverColour= button.LightColour(button._backColour, 30)
      button._textColour= wx.BLACK
      button.Refresh()

class InputLine(wx.Panel):

   def __init__(self, parent, number, mainFolder=False, defaultvalue=''):
      wx.Panel.__init__(self, parent)
      self.SetBackgroundColour(wx.NamedColor("WHITE"))
      self.sizer= wx.BoxSizer(wx.HORIZONTAL)
      self.number= number
      self.parent= parent

      inputDirLabel= wx.StaticText(self, -1, 'Input Folder #%s: ' % self.number)
      inputDirLabel.SetFont(wx.Font(
        iround(0.9*ref_font_size), wx.SWISS, wx.NORMAL, wx.FONTWEIGHT_BOLD))

      self.inputDirLabel= inputDirLabel
      self.inputDirText= wx.TextCtrl(self, -1, str(defaultvalue))
      inputDirButton= wx.Button(self, -1, '^', size=wx.Size(23,23))

      PlusLineButton= MyAquaButton(self, label='+', size=wx.Size(23,23))
      PlusLineButton.myEnable()

      ft= PlusLineButton.GetFont()
      ft.SetWeight(92)
      ft.SetPointSize( iround(1.12*ref_font_size) )
      PlusLineButton.SetFont(ft)
      PlusLineButton.SetForegroundColour('BLUE')

      self.sizer.Add(inputDirLabel , 0, wx.ALIGN_LEFT , 5)
      self.sizer.Add(self.inputDirText, 1, wx.EXPAND , 5)
      self.sizer.Add(inputDirButton , 0, wx.ALIGN_RIGHT, 5)
      self.sizer.Add(PlusLineButton , 0, wx.ALIGN_RIGHT, 5)

      if not mainFolder:
         MinusLineButton= MyAquaButton(self, label='-', size=wx.Size(23,23))
         MinusLineButton.myEnable()
         self.sizer.Add(MinusLineButton,0,wx.ALIGN_RIGHT,5)
         self.Bind(wx.EVT_BUTTON,self.OnMinus,MinusLineButton)
         ft= MinusLineButton.GetFont()
         ft.SetWeight(92)
         ft.SetPointSize( iround(1.12*ref_font_size) )
         MinusLineButton.SetFont(ft)
         MinusLineButton.SetForegroundColour('RED')

      self.SetSizer(self.sizer)

      self.inputDirText.Bind(wx.EVT_TEXT, self.OnText)#,self.inputDirText)
      self.Bind(wx.EVT_BUTTON, self.ChooseInputDir, inputDirButton)
      self.Bind(wx.EVT_BUTTON, self.OnPlus , PlusLineButton)

   def OnPlus(self, event):
      self.parent.AddInputLine(self.number+1)

# end class InputLine(wx.Panel)

class MyApp(wx.App):
    def OnInit(self):
        frame= wx.Frame(None, -1, "Hello from wxPython")
        panel= DocPanel(frame)
        frame.Show(True)
        self.SetTopWindow(frame)
        panel.Populate()
        return True

app = MyApp(0)
app.MainLoop()

Please provide a working example.
Line 28pp:
NameError: global name 'ceil' is not defined

···

Am 21.09.11 07:22, schrieb Phillip M. Feldman:

I'm generating a panel containing several buttons. For reasons that I don't
understand, the buttons overlap one another and/or are truncated by the edge of
the panel. Any suggestions will be appreciated.

Phillip

import wx
from wx.lib.agw.aquabutton import AquaButton
from numpy import ceil
button_font_point_size= 16

class DocPanel(wx.Panel):

   def __init__(self, parent, bgcolor=wx.Colour(250, 250, 250)):
      wx.Panel.__init__(self,parent)
      self.SetBackgroundColour(bgcolor)
      self.Buttons=
      self.sizer= None

   def GetDocs(self):
      return ['ABCDEFGHIJKLMNOP','QRSTUVWXYZ','123456789','Z9Y8X7W6V5U4T3S2R1Q0']

   def Populate(self):
      # If this is the first call to `Populate` then the panel has no contents
      # and self.sizer still holds the default None value
      if self.sizer is not None:
         for indx in xrange(len(self.Buttons)-1,-1,-1):
            button= self.Buttons.pop(indx)
            self.sizer.RemoveWindow(button)
            button.Destroy()

      stringList= self.GetDocs()

      # Create new sizer
      total_docs= len(stringList)
      flex_rows= int(ceil(total_docs/2.0))
      flex_cols= 2 if total_docs>=2 else 1
      self.sizer= wx.FlexGridSizer(rows=flex_rows, cols=flex_cols)
      self.SetSizer(self.sizer)

      for name in stringList:
         button= AquaButton(self, id=-1, label=name)
         self.ButtonEnable(button)
         self.Buttons.append(button)
         self.sizer.Add(button,0,wx.ALL|wx.ALIGN_CENTER,6)

      self.Layout()
      self.GetParent().Fit()
      self.GetTopLevelParent().Fit()
      self.GetTopLevelParent().Refresh()

   def ButtonEnable(self, button):
      """
      Enable User Manual or Changes Button.
      """
      button_font= wx.Font(button_font_point_size, wx.SWISS, wx.NORMAL,
         wx.FONTWEIGHT_BOLD)
      button.Enable()
      button.SetFont(button_font)
      button.SetToolTip(wx.ToolTip("This button does something."))
      button._backColour= wx.Colour(147, 202, 255)
      button._hoverColour= button.LightColour(button._backColour, 30)
      button._textColour= wx.BLACK
      button.Refresh()

   def ButtonDisable(self, button):
      """
      Disable User Manual or Changes Button.
      """
      button.Disable()
      button._backColour= wx.Colour(200, 200, 200)
      button._hoverColour= button.LightColour(button._backColour, 30)
      button._textColour= wx.BLACK
      button.Refresh()

class InputLine(wx.Panel):

   def __init__(self, parent, number, mainFolder=False, defaultvalue=''):
      wx.Panel.__init__(self, parent)
      self.SetBackgroundColour(wx.NamedColor("WHITE"))
      self.sizer= wx.BoxSizer(wx.HORIZONTAL)
      self.number= number
      self.parent= parent

      inputDirLabel= wx.StaticText(self, -1, 'Input Folder #%s: ' % self.number)
      inputDirLabel.SetFont(wx.Font(
        iround(0.9*ref_font_size), wx.SWISS, wx.NORMAL, wx.FONTWEIGHT_BOLD))

      self.inputDirLabel= inputDirLabel
      self.inputDirText= wx.TextCtrl(self, -1, str(defaultvalue))
      inputDirButton= wx.Button(self, -1, '^', size=wx.Size(23,23))

      PlusLineButton= MyAquaButton(self, label='+', size=wx.Size(23,23))
      PlusLineButton.myEnable()

      ft= PlusLineButton.GetFont()
      ft.SetWeight(92)
      ft.SetPointSize( iround(1.12*ref_font_size) )
      PlusLineButton.SetFont(ft)
      PlusLineButton.SetForegroundColour('BLUE')

      self.sizer.Add(inputDirLabel , 0, wx.ALIGN_LEFT , 5)
      self.sizer.Add(self.inputDirText, 1, wx.EXPAND , 5)
      self.sizer.Add(inputDirButton , 0, wx.ALIGN_RIGHT, 5)
      self.sizer.Add(PlusLineButton , 0, wx.ALIGN_RIGHT, 5)

      if not mainFolder:
         MinusLineButton= MyAquaButton(self, label='-', size=wx.Size(23,23))
         MinusLineButton.myEnable()
         self.sizer.Add(MinusLineButton,0,wx.ALIGN_RIGHT,5)
         self.Bind(wx.EVT_BUTTON,self.OnMinus,MinusLineButton)
         ft= MinusLineButton.GetFont()
         ft.SetWeight(92)
         ft.SetPointSize( iround(1.12*ref_font_size) )
         MinusLineButton.SetFont(ft)
         MinusLineButton.SetForegroundColour('RED')

      self.SetSizer(self.sizer)

      self.inputDirText.Bind(wx.EVT_TEXT, self.OnText)#,self.inputDirText)
      self.Bind(wx.EVT_BUTTON, self.ChooseInputDir, inputDirButton)
      self.Bind(wx.EVT_BUTTON, self.OnPlus , PlusLineButton)

   def OnPlus(self, event):
      self.parent.AddInputLine(self.number+1)

# end class InputLine(wx.Panel)

class MyApp(wx.App):
    def OnInit(self):
        frame= wx.Frame(None, -1, "Hello from wxPython")
        panel= DocPanel(frame)
        frame.Show(True)
        self.SetTopWindow(frame)
        panel.Populate()
        return True

app = MyApp(0)
app.MainLoop()

--
--------------------------------------------------
Tobias Weber
CEO

The ROG Corporation GmbH
Donaustaufer Str. 200
93059 Regensburg
Tel: +49 941 4610 57 55
Fax: +49 941 4610 57 56

www.roglink.com

GeschŠftsfŸhrer: Tobias Weber
Registergericht: Amtsgericht Regensburg - HRB 8954
UStID DE225905250 - Steuer-Nr.184/59359
--------------------------------------------------

Both problems are caused by the fact that the frame is not big enough to accommodate the layout needs of the panel. Since the buttons are being centered in their cells then when the cells are not big enough they are positioned far enough to the left of their cell to keep then centered, but that overlaps them with the button in the cell to the left.

An easy fix is to put the panel in a sizer assigned to the frame and then call frame.Fit() You should also take a look at http://wiki.wxpython.org/Widget_Inspection_Tool to help you in situations like this to figure out what is happening.

···

On 9/20/11 10:22 PM, Phillip M. Feldman wrote:

I'm generating a panel containing several buttons. For reasons that I don't
understand, the buttons overlap one another and/or are truncated by the edge of
the panel. Any suggestions will be appreciated.

--
Robin Dunn
Software Craftsman

How could I ever miss the widget inspection tool or not stumble over
anybody mentioning it before???

It sure makes complicated sizer constructions a whole lot easier, i.e.
point one visially to mistakes ...

just WOW :slight_smile:

···

Am 21.09.11 17:54, schrieb Robin Dunn:

On 9/20/11 10:22 PM, Phillip M. Feldman wrote:

I'm generating a panel containing several buttons. For reasons that
I don't
understand, the buttons overlap one another and/or are truncated by
the edge of
the panel. Any suggestions will be appreciated.

Both problems are caused by the fact that the frame is not big enough
to accommodate the layout needs of the panel. Since the buttons are
being centered in their cells then when the cells are not big enough
they are positioned far enough to the left of their cell to keep then
centered, but that overlaps them with the button in the cell to the left.

An easy fix is to put the panel in a sizer assigned to the frame and
then call frame.Fit() You should also take a look at
http://wiki.wxpython.org/Widget_Inspection_Tool to help you in
situations like this to figure out what is happening.

I don't know... I mention it (ok, I push it on people) at least a few times per week. :slight_smile:

···

On 9/21/11 10:54 AM, Tobias Weber wrote:

How could I ever miss the widget inspection tool or not stumble over
anybody mentioning it before???

--
Robin Dunn
Software Craftsman