combobox with checkable items

48 views
Skip to first unread message

ericpell...@gmail.com

unread,
Jun 3, 2022, 6:32:32 AM6/3/22
to wxPython-users
Hi all,

I created some years ago (wxPython 3.0) a combobox with checkable items. Behind the scene, it used a mixin class between wx.CheckListBox and wx.combo.ComboPopup. Recently, I had to port this code to Phoenix and I can not make it work. You will find below a snippet reproducing the code. The error I get is:

test.py:7: wxPyDeprecationWarning: Call to deprecated item. PostCreate is no longer necessary.
  self.PostCreate(wx.CheckListBox())
wx._core.wxAssertionError: C++ assertion "m_treeview != __null" failed at /tmp/build/80754af9/wxpython_1547931003892/work/ext/wxWidgets/src/gtk/listbox.cpp(478) in DoClear(): invalid listbox

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "test.py", line 92, in <module>
    TestPanel(f)
  File "test.py", line 66, in __init__
    popupCtrl = ComboCheckbox(['dfsfs','fsdfsf','sdfsfs'])
  File "test.py", line 9, in __init__
    wx.ComboPopup.__init__(self)
SystemError: <class 'property'> returned a result with an error set

Would you have any idea about how to make this code work on phoenix ?

Thanks for your help

Eric

#####################################################

import wx

class ComboCheckbox(wx.CheckListBox,wx.ComboPopup):

    def __init__(self, items, maxNumberOfItems=None):

        self.PostCreate(wx.CheckListBox())

        wx.ComboPopup.__init__(self)

        self._items = items
        self._maxNumberOfItems = maxNumberOfItems
        self._currentItem = -1

    def OnMotion(self, event):

        item  = self.HitTest(event.GetPosition())
        if item >= 0:
            self.Select(item)
            self._currentItem = item

    def Create(self, parent):

        wx.CheckListBox.Create(self,parent, -1, choices=self._items)
        self.Bind(wx.EVT_MOTION, self.OnMotion)
        self.Bind(wx.EVT_LEFT_DOWN, self.on_check_item)
        if not self.IsEmpty():
            self.Check(0)

        return True

    def GetControl(self):
        return self

    def GetAdjustedSize(self, minWidth, prefHeight, maxHeight):
         size = self.GetControl().GetSize()
         return wx.Size(minWidth, size[1])

    def GetStringValue(self):
        return self.GetCheckedStrings()

    def on_check_item(self, event):

        # Control only if ele;ent is checked
        if not self.IsChecked(self._currentItem):

            # Control max number of items
            if self._maxNumberOfItems is None:
                # Accept the event
                self.Check(self._currentItem, True)
            else:
                # Control the number of checked items
                nCheckedItems = len(self.GetChecked())
                if nCheckedItems < self._maxNumberOfItems:
                    # Chech the item
                    self.Check(self._currentItem, True)
        else:
            self.Check(self._currentItem, False)

class TestPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)

        comboCtrl = wx.ComboCtrl(self, wx.ID_ANY, "", (20,20))

        popupCtrl = ComboCheckbox(['dfsfs','fsdfsf','sdfsfs'])

        # It is important to call SetPopupControl() as soon as possible
        comboCtrl.SetPopupControl(popupCtrl)

        # Populate using wx.ListView methods
        popupCtrl.AddItem("First Item")
        popupCtrl.AddItem("Second Item")
        popupCtrl.AddItem("Third Item")


#----------------------------------------------------------------------

def runTest(frame, nb, log):
    win = TestPanel(nb, log)
    return win

#----------------------------------------------------------------------


if __name__ == '__main__':

    app = wx.App()

    f = wx.Frame(None)

    TestPanel(f)

    f.Show()

    app.MainLoop()
Reply all
Reply to author
Forward
0 new messages