CheckListBox overly left-padding inserted strings

Hi!

I’m writing an app that uses a CheckListBox that I fill filenames after it’s created. I’m using the InsertObjects() method to insert the items in an otherwise empty control. However, there is a humongous amount of whitespaced to the left of each item. I broke the example down to the following code which for reasons I’m not understanding, works correctly:

import os
import glob
import wx

class MyPanel(wx.Panel):

    source_directory = 'data'

    def __init__(self, parent):
        super().__init__(parent)

        self.main_sizer = wx.BoxSizer();
        self.left_panel_sizer = wx.BoxSizer(wx.VERTICAL);
        self.right_panel_sizer = wx.BoxSizer(wx.VERTICAL);

        lbl = wx.StaticText(self, label='CheckListBox Test')
        self.left_panel_sizer.Add(lbl, 0, wx.ALL, 5)

        self.clb = wx.CheckListBox(self, size=(300, 200))
        self.left_panel_sizer.Add(self.clb, 0, wx.ALL, 5)
        self.main_sizer.Add(self.left_panel_sizer, 0, wx.ALL, 5)

        self.load_btn = wx.Button(self, label='Load')
        self.load_btn.Bind(wx.EVT_BUTTON, self.load_files)
        self.right_panel_sizer.Add(self.load_btn, 0, wx.ALL, 5)

        self.main_sizer.Add(self.right_panel_sizer, 0, wx.ALL, 5)

        self.SetSizer(self.main_sizer)


    def load_files(self, event):
        mask = os.path.join(self.source_directory, "*.xlsx")
        input_files = []
        for f in glob.glob(mask):
            input_files.append(os.path.split(f)[1])
        self.clb.InsertItems(input_files, 0)


class MainFrame(wx.Frame):

    def __init__(self):
        super().__init__(None, title='CheckListBox Test')
        panel = MyPanel(self)
        self.Show()


if __name__ == '__main__':
    app = wx.App(redirect=False)
    frame = MainFrame()
    app.MainLoop()

The code above produces the following when the Load button is clicked:

(I’ve edited the posts to provide images to illustrate what I’m seeing)

The same code in my main app produces the following:

I’ve checked the strings in the list to see if they have any leading space (they don’t), so I’m sort of confused.

MacOS 10.15.3 (Catalina)
Python 3.7.7
wxPython 4.0.7.post2

Any help appreciated!

Minimal Code Sample to reproduce:

main.py

import os
import glob
import wx
import wx.grid
from ObjectListView import ObjectListView, ColumnDefn
from MainPanel import MainPanel

class MainFrame(wx.Frame):

    def __init__(self):
        super().__init__(None, title='Spreadsheet Scorer', size=wx.Size(734,466))
        panel = MainPanel(self)
        self.Show()

    def OnExitApp(self, event):
        self.frame.Close()


if __name__ == '__main__':
    app = wx.App(redirect=False)
    frame = MainFrame()
    app.MainLoop()

MainPanel.py:

import os
import glob
import wx
import wx.grid
from ObjectListView import ObjectListView, ColumnDefn

class MainPanel(wx.Panel):

    def __init__(self, parent):
        super().__init__(parent)

        self.selected_files = []

        self.main_sizer = wx.BoxSizer()
        self.create_left_pane()
        self.create_right_pane()


    def create_left_pane(self):
        left_pane_sizer = wx.BoxSizer(wx.VERTICAL)

        # add the source directory label
        row_sizer = wx.BoxSizer()
        lbl = wx.StaticText(self, label='Source Directory')
        row_sizer.Add(lbl, 0, wx.ALL)
        left_pane_sizer.Add(row_sizer, 0, wx.ALL)

        # add the source directory text
        row_sizer = wx.BoxSizer()
        self.txt_source_dir = wx.TextCtrl(self, style=wx.TE_READONLY,
                                          size=(276,-1))
        row_sizer.Add(self.txt_source_dir, 0, wx.ALL)

        self.btn_source_dir = wx.Button(self, wx.ID_ANY, style=wx.BU_EXACTFIT)
        self.btn_source_dir.SetBitmapLabel(wx.ArtProvider.GetBitmap(wx.ART_FOLDER,
                                                                 wx.ART_MENU))
        self.btn_source_dir.Bind(wx.EVT_BUTTON, self.on_src_dir_btn_press)
        row_sizer.Add(self.btn_source_dir, 0, wx.ALL)
        left_pane_sizer.Add(row_sizer, 0, wx.ALL)

        # Add the checklistbox for available files
        row_sizer = wx.BoxSizer()
        self.clb_selected_files = wx.CheckListBox(self, size=(300,280))
        row_sizer.Add(self.clb_selected_files, 0, wx.ALL)
        left_pane_sizer.Add(row_sizer, 0, wx.ALL)


        self.main_sizer.Add(left_pane_sizer, 1, wx.ALL, 10)
        self.SetSizer(self.main_sizer)

    def get_dir(self):
        with wx.DirDialog(self, 'Select a directory',
                          style=wx.DD_DEFAULT_STYLE) as dlg:
            if dlg.ShowModal() == wx.ID_OK:
                return dlg.GetPath()

    def on_src_dir_btn_press(self, event):
        self.source_directory = self.get_dir()
        self.txt_source_dir.SetValue(self.source_directory)
        self.load_file_names()

    def load_file_names(self):
        # clear out the CheckListBox
        self.clb_selected_files.Clear()
        mask = os.path.join(self.source_directory, "*.xlsx")
        self.input_files = []
        for f in glob.glob(mask):
            self.input_files.append(os.path.split(f)[1].strip())
        if len(self.input_files) > 0:
            self.clb_selected_files.InsertItems(self.input_files, 0)

    def create_right_pane(self):
        right_pane_sizer = wx.BoxSizer(wx.VERTICAL)

This issue has been known for a while, but it’s not clear yet what the cause is.

Is there any sort of workaround or is the workaround to just not use this widget?

I also upgraded to Python 3.8.2 and that had no effect FWIW.

There’s no workaround that I know of, but it’s not hard to accomplish something similar by combining a wxListCtrl with a wx.lib.mixins.listctrl.CheckListCtrlMixin.

Or, if you’re already using 4.1.0-dev, or don’t mind waiting a little longer for the release, then it’s possible to turn on a checkbox feature in the wx.ListCtrl without the mixin class.

What is the trick for turning on the checkbox in the wx.ListCtrl in 4.1-dev?

https://wxpython.org/Phoenix/docs/html/wx.ListCtrl.html#wx.ListCtrl.EnableCheckBoxes

Thanks for the pointer!!!