pythonwxpython

How to create a CheckListBox in wx python that allows multiple selections - wxComboBox


I am trying to create a collapsible checkbox using wx python 2.9.5.0 with Python 2.7 that allows multiple options to be checked.

The following qustion seems to get close, but it's missing a few major things. It references the "ComboCtrl example in the demo". However, when I tried to run that sample, I got an error that wx doesn't have an attribute ComboCtrl. That was fixed by calling wx.combo.ComboCtrl. However, I can't seem to find ListViewComboPopup() in any combination of wx or wx.combo.

Where does that ListViewComboPopup() function live?

For Reference, here is my current attempt at the code:

class MyFrame ( wx.Frame ):
    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

        bSIZER = wx.BoxSizer( wx.VERTICAL )

        comboCtrl = combo.ComboCtrl(self, wx.ID_ANY, "")
        popupCtrl = wx.combo.ListViewComboPopup()

        # It is important to call SetPopupControl() as soon as possible
        comboCtrl.SetPopupControl(popupCtrl)
        # Populate using wx.ListView methods
        popupCtrl.InsertItem(popupCtrl.GetItemCount(), "First Item")
        popupCtrl.InsertItem(popupCtrl.GetItemCount(), "Second Item")
        popupCtrl.InsertItem(popupCtrl.GetItemCount(), "Third Item")

        bSIZER.Add( comboCtrl, 1, wx.ALL, 

        self.SetSizer( bSIZER )
        self.Layout()

        self.Centre( wx.BOTH )

    def __del__( self ):
        pass

Running that gives the following error: AttributeError: 'module' object has no attribute 'ListViewComboPopup'

Once I get this working, I'm still a few steps from creating the drop down menu with multiple options, but I this is the big current stumbling block.


Solution

  • See http://zetcode.com/wxpython/advanced/ and check out the section on

    CheckListCtrl The code is as follows:

    #!/usr/bin/python
    
    # repository.py
    
    import wx
    import sys
    from wx.lib.mixins.listctrl import CheckListCtrlMixin, ListCtrlAutoWidthMixin
    
    packages = [('abiword', '5.8M', 'base'), ('adie', '145k', 'base'),
        ('airsnort', '71k', 'base'), ('ara', '717k', 'base'), ('arc', '139k', 'base'),
        ('asc', '5.8M', 'base'), ('ascii', '74k', 'base'), ('ash', '74k', 'base')]
    
    class CheckListCtrl(wx.ListCtrl, CheckListCtrlMixin, ListCtrlAutoWidthMixin):
        def __init__(self, parent):
            wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT | wx.SUNKEN_BORDER)
            CheckListCtrlMixin.__init__(self)
            ListCtrlAutoWidthMixin.__init__(self)
    
    
    class Repository(wx.Frame):
        def __init__(self, parent, id, title):
            wx.Frame.__init__(self, parent, id, title, size=(450, 400))
    
            panel = wx.Panel(self, -1)
    
            vbox = wx.BoxSizer(wx.VERTICAL)
            hbox = wx.BoxSizer(wx.HORIZONTAL)
    
            leftPanel = wx.Panel(panel, -1)
            rightPanel = wx.Panel(panel, -1)
    
            self.log = wx.TextCtrl(rightPanel, -1, style=wx.TE_MULTILINE)
            self.list = CheckListCtrl(rightPanel)
            self.list.InsertColumn(0, 'Package', width=140)
            self.list.InsertColumn(1, 'Size')
            self.list.InsertColumn(2, 'Repository')
    
            for i in packages:
                index = self.list.InsertStringItem(sys.maxint, i[0])
                self.list.SetStringItem(index, 1, i[1])
                self.list.SetStringItem(index, 2, i[2])
    
            vbox2 = wx.BoxSizer(wx.VERTICAL)
    
            sel = wx.Button(leftPanel, -1, 'Select All', size=(100, -1))
            des = wx.Button(leftPanel, -1, 'Deselect All', size=(100, -1))
            apply = wx.Button(leftPanel, -1, 'Apply', size=(100, -1))
    
    
            self.Bind(wx.EVT_BUTTON, self.OnSelectAll, id=sel.GetId())
            self.Bind(wx.EVT_BUTTON, self.OnDeselectAll, id=des.GetId())
            self.Bind(wx.EVT_BUTTON, self.OnApply, id=apply.GetId())
    
            vbox2.Add(sel, 0, wx.TOP, 5)
            vbox2.Add(des)
            vbox2.Add(apply)
    
            leftPanel.SetSizer(vbox2)
    
            vbox.Add(self.list, 1, wx.EXPAND | wx.TOP, 3)
            vbox.Add((-1, 10))
            vbox.Add(self.log, 0.5, wx.EXPAND)
            vbox.Add((-1, 10))
    
            rightPanel.SetSizer(vbox)
    
            hbox.Add(leftPanel, 0, wx.EXPAND | wx.RIGHT, 5)
            hbox.Add(rightPanel, 1, wx.EXPAND)
            hbox.Add((3, -1))
    
            panel.SetSizer(hbox)
    
            self.Centre()
            self.Show(True)
    
        def OnSelectAll(self, event):
            num = self.list.GetItemCount()
            for i in range(num):
                self.list.CheckItem(i)
    
        def OnDeselectAll(self, event):
            num = self.list.GetItemCount()
            for i in range(num):
                self.list.CheckItem(i, False)
    
        def OnApply(self, event):
            num = self.list.GetItemCount()
            for i in range(num):
                if i == 0: self.log.Clear()
                if self.list.IsChecked(i):
                    self.log.AppendText(self.list.GetItemText(i) + '\n')
    
    app = wx.App()
    Repository(None, -1, 'Repository')
    app.MainLoop()
    

    Result: enter image description here