Reputation: 105
I have a ListCtrl that can update itself with various items. To do that, I empty it, and than I append several items.
Then I want to catch the EVT_LIST_ITEM_FOCUSED event. On Windows, Unix and MacOS, it works fine.
Finally, I want to catch the event after updating my list. That happen automatically on Unix and MacOS, but it's not the case on Windows. That's why I would like to generate an event at the end of the "update()" method.
Example in code :
import wx
class MainFrame(wx.Frame):
def __init__(self):
super().__init__(None)
self.Show()
# Create the ListCtrl
self.list_ctrl = wx.ListCtrl(self, style=wx.LC_REPORT)
self.list_ctrl.AppendColumn("Column")
# Bind the event to the callback function
self.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.on_focus, self.list_ctrl)
# Fill the list with fruits
self.update(["apples", "bananas", "pears"])
def update(self, name_list):
"""Refill the ListCtrl with the content of the list."""
# Empty the ListCtrl
self.list_ctrl.DeleteAllItems()
# Refill it
for element in name_list:
self.list_ctrl.Append([element])
def on_focus(self, event):
"""Print what is currently focused."""
focused = event.GetItem().GetText()
if focused == "":
print("No focus.")
else:
print(f"{focused} is focused.")
app = wx.App()
main_frame = MainFrame()
app.MainLoop()
This code print "apples is focused" at the start of the program with both Unix and MacOS. On Windows, it print nothing, because the event is not triggered. What I want is getting the message "apples is focused" on Windows.
Constraints :
Skip()
it to the Panel higher in the hierarchie.self.list_ctrl.Focus(0)
doesn't work, as it does nothing when there are no item.Thnks for your help and have a nice day.
Upvotes: 0
Views: 326
Reputation: 22448
I provide the code below with reservations.
Your example code and explanation are at odds with each other.
You refer to skipping the event to a higher panel and yet your example has no such code. So we are left in a position where we have a stated requirement but with no idea how, why or when it is to be implemented.
There is a distinct difference between Focused and Selected. I suggest that in this circumstance, you would be better served to use Selected.
For the record, despite your comment, with a listctrl with no items try on Linux either self.list_ctrl.Select(0)
or self.list_ctrl.Focus(0)
both will crash your code SetItemState(): invalid list ctrl item index in SetItem
.
import wx
class MainFrame(wx.Frame):
def __init__(self):
super().__init__(None)
self.some_sets = {
"fruits": ["apples", "bananas", "pears"],
"instruments": ["flutes", "drums", "guitars"],
"empty": [],
}
self.list_ctrl = wx.ListCtrl(self, style=wx.LC_REPORT)
self.list_ctrl.AppendColumn("Column")
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.on_focus, self.list_ctrl)
#self.update("empty")
self.update("fruits")
self.Show()
def update(self, set_name):
"""Refill the ListCtrl."""
# Empty the ListCtrl
self.list_ctrl.DeleteAllItems()
# Refill it
for element in self.some_sets[set_name]:
self.list_ctrl.Append([element])
if self.list_ctrl.GetItemCount():
#self.list_ctrl.Focus(0)
self.list_ctrl.Select(0)
else:
self.on_focus(None)
def on_focus(self, event):
"""Do something."""
if event:
focused = event.GetItem().GetText()
print(f"{focused} is Selected.")
else:
print("No focus.")
app = wx.App()
main_frame = MainFrame()
app.MainLoop()
Upvotes: 1
Reputation: 105
Ok, so I found a way to work around the problem by getting rid of one constraint (I wanted to Skip()
the event if needed).
Here's the code I use.
def update(self, name_list):
"""Refill the ListCtrl with the content of the list."""
self.list_ctrl.DeleteAllItems()
for element in name_list:
self.list_ctrl.Append([element])
# Call the callback functions
if self.list_ctrl.GetItemCount() == 0:
# Our custom one if there's no item in the list
self.on_focus_custom(None)
else:
# Else the classic function
self.list_ctrl.Focus(0)
def on_focus(self, event):
"""Call the on_focus_custom method with proper arguments."""
focused = event.GetItem().GetText()
if focused == "":
self.on_focus_custom(None)
else:
self.on_focus_custom(focused)
def on_focus_custom(self, focused):
"""Print what is currently focused."""
if focused is None:
print("No focus.")
else:
print(f"{focused} is focused.")
# Here, we can't skip the event, because we haven't one.
# So here a mediocre solution I found.
# Thats a method I defined in the upper Panel.
# self.GetParent().on_focus_custom(focused)
I you have cleaner ways to do it, I'm interested.
Upvotes: 0