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?