views:

396

answers:

3

Dear all,

I'm working with wxpython (2.8) with python 2.5. is it possible to force a wx.CheckBox to display its label on multiple lines? I'd like to be able to do the same as wx.StaticText.Wrap(width)

See the attached example: the wx.CheckBox is 200 px wide, but it's label does not fit in this space.

Any help is really appreciated! Thanks a lot Mauro

#example starts here

import wx


class MyFrame(wx.Frame):
   def __init__(self):
       wx.Frame.__init__(self,  None, title="Hello World", size=
(300,200))

       self.panel = wx.Panel(self,  -1)
       myVSizer = wx.BoxSizer(wx.VERTICAL)

       #instantiating a checkbox 200 px wide. but the label is too
long
       cb = wx.CheckBox(self.panel,  -1,  label="This is a very very
long label for 200 pixel wide cb!",  size =wx.Size(200, -1))

       myVSizer.Add( cb, 1)

       self.panel.SetSizer(myVSizer)
       myVSizer.Layout()


app = wx.App(redirect=True)
top = MyFrame()
top.Show()
app.MainLoop()
+1  A: 
tom10
It does not work for me!
Mauro Bianchi
Hmmm... it works for me on Linux. What OS are you using?
tom10
Also, I posted a screenshot just to be sure that we're talking about the same thing here, but I assume this is what you're wanting, right?
tom10
yes, that would be what I want. I'm actually on Windows (not a choice, a constraint...) thanks anyway
Mauro Bianchi
A: 

Instead of using checkbox with text, use a no label checkbox with static text for desired effect e.g.

import wx


class MyFrame(wx.Frame):
   def __init__(self):
      wx.Frame.__init__(self,  None, title="Hello World", size=(300,200))

      self.panel = wx.Panel(self,  -1)
      myVSizer = wx.BoxSizer(wx.VERTICAL)

      # use checkbox + static text to wrap the text
      myHSizer = wx.BoxSizer(wx.HORIZONTAL)
      cb = wx.CheckBox(self.panel,  -1,  label="")
      label = wx.StaticText(self.panel, label="This is a very very long label for 100 pixel wide cb!", size=(100,-1))
      label.Wrap(100)
      myHSizer.Add(cb, border=5, flag=wx.ALL)
      myHSizer.Add(label, border=5, flag=wx.ALL)

      myVSizer.Add(myHSizer)

      self.panel.SetSizer(myVSizer)
      myVSizer.Layout()


app = wx.App(redirect=True)
top = MyFrame()
top.Show()
app.MainLoop()

this has added benefit that with different layouts you can make text centre to checkbox, or on left or right or any other place

Anurag Uniyal
+2  A: 

Hi Mauro, what about something like this? Flex! (I've made it a radio button to show that it still behaves like one)

import wx
import textwrap

class MultilineRadioButton(wx.RadioButton):
        def __init__(self, parent, id=-1, label=wx.EmptyString, wrap=10, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, validator=wx.DefaultValidator, name=wx.RadioButtonNameStr):
            wx.RadioButton.__init__(self,parent,id,'',pos,size,style,validator,name)
            self._label = label
            self._wrap = wrap
            lines = self._label.split('\n')
            self._wrappedLabel = []
            for line in lines:
                self._wrappedLabel.extend(textwrap.wrap(line,self._wrap))

            self._textHOffset = 20
            dc = wx.ClientDC(self)
            font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
            dc.SetFont(font)
            maxWidth = 0
            totalHeight = 0
            lineHeight = 0
            for line in self._wrappedLabel:
                width, height = dc.GetTextExtent(line)
                maxWidth = max(maxWidth,width)
                lineHeight = height
                totalHeight += lineHeight 

            self._textHeight = totalHeight

            self.SetInitialSize(wx.Size(self._textHOffset + maxWidth,totalHeight))
            self.Bind(wx.EVT_PAINT, self.OnPaint)

        def OnPaint(self, event):
            dc = wx.PaintDC(self)
            self.Draw(dc)
            self.RefreshRect(wx.Rect(0,0,self._textHOffset,self.GetSize().height))
            event.Skip()

        def Draw(self, dc):
            dc.Clear()
            font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
            dc.SetFont(font)
            height = self.GetSize().height
            if height > self._textHeight:
                offset = height / 2 - self._textHeight / 2
            else:
                offset = 0
            for line in self._wrappedLabel:
                width, height = dc.GetTextExtent(line)
                dc.DrawText(line,self._textHOffset,offset)
                offset += height


class HFrame(wx.Frame):
   def __init__(self,pos=wx.DefaultPosition):
       wx.Frame.__init__(self,None,title="Hello World",size=wx.Size(600,400),pos=pos)

       self.panel = wx.Panel(self,-1)
       sizer = wx.BoxSizer(wx.HORIZONTAL)

       cb = RadioButton(self.panel,-1,label="This is a very very long label for the control!",wrap=10)
       sizer.Add(cb,1)

       cb = RadioButton(self.panel,-1,label="This is a very very long label for the control!",wrap=10)
       sizer.Add(cb,1)

       cb = RadioButton(self.panel,-1,label="This is a very very long label for the control!",wrap=10)
       sizer.Add(cb,1)

       self.panel.SetSizer(sizer)
       sizer.Layout()


class VFrame(wx.Frame):
   def __init__(self,pos=wx.DefaultPosition):
       wx.Frame.__init__(self,None,title="Hello World",size=wx.Size(600,400),pos=pos)

       self.panel = wx.Panel(self,-1)
       sizer = wx.BoxSizer(wx.VERTICAL)

       cb = RadioButton(self.panel,-1,label="This is a very very long label for the control!",wrap=10)
       sizer.Add(cb,1)

       cb = RadioButton(self.panel,-1,label="This is a very very long label for the control!",wrap=10)
       sizer.Add(cb,1)

       cb = RadioButton(self.panel,-1,label="This is a very very long label for the control!",wrap=10)
       sizer.Add(cb,1)

       self.panel.SetSizer(sizer)
       sizer.Layout()


app = wx.App(redirect=False)
htop = HFrame(pos=wx.Point(0,50))
htop.Show()
vtop = VFrame(pos=wx.Point(650,50))
vtop.Show()
app.MainLoop()
luca
Great Luca, this is the perfect solution! And thanks for sharing.This is a feature I'd like to see merged into wxPython itself.(For those who cannot run the example: there's a little typo, just replace all 'RadioButton' instances with 'MultilineRadioButton' in VFrame and HFrame constructors.)
Mauro Bianchi