【问题标题】:Generate EVT_LIST_ITEM_FOCUSED on ListCtrl update在 ListCtrl 更新时生成 EVT_LIST_ITEM_FOCUSED
【发布时间】:2020-07-22 05:39:09
【问题描述】:

我有一个 ListCtrl 可以使用各种项目进行自我更新。 为此,我将其清空,然后附加几个项目。

然后我想捕捉 EVT_LIST_ITEM_FOCUSED 事件。 在 Windows、Unix 和 MacOS 上,它运行良好。

最后,我想在更新列表后赶上活动。 这在 Unix 和 MacOS 上自动发生,但在 Windows 上并非如此。 这就是为什么我想在“update()”方法结束时生成一个事件。

代码示例:

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()

此代码在 Unix 和 MacOS 程序的开头打印“apples is focus”。 在 Windows 上,它什么也不打印,因为事件没有被触发。 我想要的是在 Windows 上收到“苹果专注于”的消息。

约束:

  • 我想使用一个事件,因为我打算将它Skip() 发送到层次结构中更高的面板。
  • 我想用我选择的项目文本设置这个事件,这样如果 ListCtrl 中没有项目,程序可以打印“无焦点”。因此调用self.list_ctrl.Focus(0) 不起作用,因为没有项目时它什么也不做。

感谢您的帮助,祝您有美好的一天。

【问题讨论】:

  • 如果列表中没有元素,则没有焦点,self.list_ctrl.Focus(0) 将使程序崩溃。还是我误解了你的问题
  • @RolfofSaxony 它不会使程序崩溃,而是什么都不做。但这不是问题:我只想生成一个事件来触发我的on_focus 方法,而不管我的列表中有多少项目。
  • 如果没有项目,就没有事件。您可以随时使用on_focus(None)
  • @RolfofSaxony 我考虑过,但我将这个事件跳过到层次结构中更高的面板,所以我真的想构建一个事件对象。
  • 您的代码示例确实应该说明您的问题。希望通过这个过程,虽然您没有得到答案,但您已经确定了您的问题。

标签: wxpython listctrl


【解决方案1】:

好的,所以我找到了一种通过摆脱一个约束来解决问题的方法(如果需要,我想Skip() 事件)。

这是我使用的代码。

    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)

你有更简洁的方法,我很感兴趣。

【讨论】:

    【解决方案2】:

    我提供以下代码以进行保留。

    您的示例代码和解释相互矛盾。
    您指的是将事件跳过到更高的面板,但您的示例没有这样的代码。因此,我们处于一个有明确要求但不知道如何、为什么或何时实施的境地。

    专注和选择之间有明显的区别。我建议在这种情况下,您最好使用 Selected。

    作为记录,尽管您发表了评论,但在 Linux 上使用没有项目的 listctrl 尝试 self.list_ctrl.Select(0)self.list_ctrl.Focus(0) 两者都会使您的代码崩溃 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()
    

    【讨论】:

      猜你喜欢
      • 2012-10-09
      • 1970-01-01
      • 1970-01-01
      • 2012-07-01
      • 1970-01-01
      • 2013-08-24
      • 1970-01-01
      • 2015-08-05
      • 2014-06-18
      相关资源
      最近更新 更多