Search code examples
pythonuser-interfacewxwidgetswxpython

wxpython checkbox label not shown completely, some letters are hidden by others


I have a lot of checkboxes and they have different label length, when I use the gridsizer to show them, the label are not shown completely. I find that when the number of checkboxes grows, the Dialog size remains the same. How can I get show all the checkboxes and the labels? Below is the code and image:

# -*- coding: utf-8 -*-
import wx
import math


class Example(wx.Dialog):
    def __init__(self, cb_titles, title):
        super().__init__(None, title=title)
        self.cb_labels = cb_titles
        self.panel = wx.Panel(self)
        self.initUI()
        self.Centre()
        self.ShowModal()

    def initUI(self):
        vbox = wx.BoxSizer(wx.VERTICAL)  # I use vbox here because I need to add other items below this grid sizer, not shown in the example.
        self.set_grid(vbox)
        border = wx.BoxSizer()
        border.Add(vbox, 1, wx.ALL | wx.EXPAND, 10)
        self.panel.SetSizer(border)
        self.panel.Fit()

    def set_grid(self, vbox):
        n_cbs = len(self.cb_labels)
        n_col = int(math.sqrt(n_cbs))
        n_row = n_col
        while n_row * n_col < n_cbs:
            n_row += 1
        sb = wx.StaticBox(self.panel, -1, 'CheckBoxes:')
        sb_sizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
        grid_sizer = wx.GridSizer(n_row, n_col, 30)

        for i in range(n_cbs):
            cb_label = self.cb_labels[i]
            cb = wx.CheckBox(self.panel, label=cb_label)
            grid_sizer.Add(cb, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
        sb_sizer.Add(grid_sizer, 1, wx.ALL|wx.CENTER, 10)
        vbox.Add(sb_sizer, 1, wx.CENTER, 0)





app = wx.App()
cb_titles = ["aaaaaaaaaaa", "bbbbbbb", "cccccccccc", "ddddddd", "eeeeeeee", "ffffffffff", "DDDDDDDDDD", 'FFFFFFFFFFFFFF', "GGGGGGGGGG"] * 3  # you can change this number
Example(cb_titles, title ='Question Example')
app.MainLoop()

enter image description here

I want to use the Dialog widget, you can see in the picture the label is not shown completely. Besides, when I click the cross button, the Dialog closes but the program is not ended, how to end it properly?


Solution

  • I think that you are going to have to calculate and set the size of the dialog based on the longest label length (I may be wrong).

    The longest string in a list can be found with:

    max(a_list,key=len)
    

    You are also going to have to find the point size of the characters that you are using.

    This is my first stab at your code, hopefully you will find it useful if not exactly what you want.

    # -*- coding: utf-8 -*-
    import wx
    import math
    
    
    class Example(wx.Dialog):
        def __init__(self, cb_titles, title):
            super().__init__(None, title=title)
            self.cb_labels = cb_titles
            self.panel = wx.Panel(self)
            self.initUI()
            self.Centre()
    
        def initUI(self):
            vbox = wx.BoxSizer(wx.VERTICAL)  # I use vbox here because I need to add other items below this grid sizer, not shown in the example.
            self.set_grid(vbox)
            border = wx.BoxSizer()
            border.Add(vbox, 1, wx.ALL | wx.EXPAND, 10)
            self.panel.SetSizer(border)
            self.panel.Fit()
    
        def set_grid(self, vbox):
            n_cbs = len(self.cb_labels)
            n_col = int(math.sqrt(n_cbs))
            n_row = n_col
            while n_row * n_col < n_cbs:
                n_row += 1
            sb = wx.StaticBox(self.panel, -1, 'CheckBoxes:')
            sb_sizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
            grid_sizer = wx.GridSizer(n_row, n_col, 30)
    
            for i in range(n_cbs):
                cb_label = self.cb_labels[i]
                cb = wx.CheckBox(self.panel, label=cb_label)
                grid_sizer.Add(cb, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
            sb_sizer.Add(grid_sizer, 1, wx.ALL|wx.CENTER, 10)
            vbox.Add(sb_sizer, 1, wx.CENTER, 0)
    
            #Set the size based on the number of columns and
            #the length of the longest label + margins
            self.font = wx.SystemSettings.GetFont(wx.SYS_SYSTEM_FONT)
            pt = self.font.GetPointSize()
            w=(len(max(self.cb_labels,key=len))*n_col)+(pt*(n_col - 1))
            w=(w*pt)
            self.SetSize(w,-1)
    
    app = wx.App()
    cb_titles = ["aaaaaaaaaaa", "bbbbbbb", "cccccccccc", "ddddddd", "eeeeeeee", "ffffffffff", "DDDDDDDDDD", 'FFFFFFFFFFFFFF', "GGGGGGGGGG"] * 5  # you can change this number
    
    dlg = Example(cb_titles, title ='Question Example')
    dlg.ShowModal()
    dlg.Destroy()
    app.MainLoop()
    

    Finally, take the ShowModal() out of the dialog and place it outside, so that you can use the Destroy() function, which will end the dialog correctly.
    You could leave the ShowModal in the dialog but then you would have to code the Destroy in there as well.

    enter image description here