I have an application with a wx.ListCtrl configured for report mode and multiple selections.
I have noticed that after calling the DeleteItem() method, the value returned by GetSelectedItemCount() doesn’t match the actual number of items selected in the listctrl.
Here is a simplified example that demonstrates the issue:
import wx
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.SetSize((400, 300))
self.SetTitle("Test ListCtrl")
self.panel = wx.Panel(self, wx.ID_ANY)
main_sizer = wx.BoxSizer(wx.VERTICAL)
self.list_ctrl = wx.ListCtrl(self.panel, wx.ID_ANY, style=wx.LC_HRULES | wx.LC_REPORT | wx.LC_VRULES)
self.list_ctrl.AppendColumn("A", format=wx.LIST_FORMAT_LEFT, width=-1)
main_sizer.Add(self.list_ctrl, 1, wx.EXPAND, 0)
button_sizer = wx.BoxSizer(wx.HORIZONTAL)
main_sizer.Add(button_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.BOTTOM | wx.TOP, 8)
self.reload_button = wx.Button(self.panel, wx.ID_ANY, "Reload Items")
button_sizer.Add(self.reload_button, 0, wx.RIGHT, 16)
self.delete_button = wx.Button(self.panel, wx.ID_ANY, "Delete Selected")
button_sizer.Add(self.delete_button, 0, 0, 0)
self.panel.SetSizer(main_sizer)
self.Layout()
self.Bind(wx.EVT_BUTTON, self.OnDeleteSelected, self.delete_button)
self.Bind(wx.EVT_BUTTON, self.OnReloadItems, self.reload_button)
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelected, self.list_ctrl)
self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnDeselected, self.list_ctrl)
self.insertItems()
def insertItems(self):
for i in range(0, 6):
self.list_ctrl.InsertItem(i, "Item %d" % i)
def OnDeleteSelected(self, event):
indices = []
index = self.list_ctrl.GetFirstSelected()
while index != wx.NOT_FOUND:
indices.append(index)
index = self.list_ctrl.GetNextSelected(index)
for index in reversed(indices):
self.list_ctrl.DeleteItem(index)
print("Deleted item %d" % index)
def OnDeselected(self, event):
print("Deselected index %d, num selected = %d" % (event.GetIndex(), self.list_ctrl.GetSelectedItemCount()))
def OnReloadItems(self, _event):
self.list_ctrl.DeleteAllItems()
self.insertItems()
def OnSelected(self, event):
print("Selected index %d, num selected = %d" % (event.GetIndex(), self.list_ctrl.GetSelectedItemCount()))
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, wx.ID_ANY, "")
self.SetTopWindow(self.frame)
self.frame.Show()
return True
if __name__ == "__main__":
app = MyApp(0)
app.MainLoop()
If I run this code and then do the following steps:
Click on Item 0
Click on Item 1
Click on “Delete Selected” button
Click on Item 3
Click on Item 4
It produces the following output:
Selected index 0, num selected = 1
Deselected index 0, num selected = 0
Selected index 1, num selected = 1
Deleted item 1
Selected index 2, num selected = 2
Deselected index 2, num selected = 1
Selected index 3, num selected = 2
Notice that after calling DeleteItem(), the values returned by GetSelectedItemCount() are wrong. It seems to be treating the item(s) that have been deleted as still being part of the selected items?
If I then click on the “Reload Items” button, GetSelectedItemCount() starts returning the correct values once more.
I am using Python 3.10.6 + wxPython 4.2.0 gtk3 (phoenix) wxWidgets 3.2.0 on Linux Mint 21.1.
Is this a bug, or am I missing something?


