python - 在 wxPython 中,如何绑定(bind)到循环中的单独对象(包括参数)?

标签 python wxpython

我不确定我是否正确地表达了这个问题,代码可能会更清晰。

我正在向 WxPython 应用程序添加一个非常简单的插件系统,其中插件选项只是添加到子菜单中,一旦单击它们,就会执行插件的操作。我对 wx 还很陌生,所以我可能做错了一些简单的事情,所以我很乐意被告知。

以下代码按预期工作,并调用了单击的菜单选项的插件“performAction”方法。

for plugin in self.pluginManager.plugins:
    wxId = wx.NewId()
    plugin_submenu.Append(wxID,plugin.displayName)
    canvas.Bind(wx.EVT_MENU, plugin.performAction)

我也想向插件操作添加参数,这导致我使用 lambda,因为“bind”方法的第二个参数应该是可调用的。这似乎是一个相当不起眼的变化:

for plugin in self.pluginManager.plugins:
    wxId = wx.NewId()
    plugin_submenu.Append(wxID,plugin.displayName)
    canvas.Bind(wx.EVT_MENU, lambda evt, temp=objArgs: plugin.performAction(evt,temp)

this link所述。但是,当我这样做时,无论实际单击哪个菜单选项,最后绑定(bind)的插件对象都会被调用。我真的不确定为什么行为从第一个代码示例更改为第二个代码示例,但确实如此,我很困惑。

那么,有谁知道为什么会发生这种情况,我该怎么做才能得到我期望的行为?

最佳答案

你的问题是Python的作用域规则。在第一种情况下,您已将 plugin 的特定实例绑定(bind)到 Canvas ,在执行此代码时

在第二种情况下,您再次在执行此代码时将一个特定函数(您的 lambda 函数)绑定(bind)到 Canvas 。不幸的是,您的 lambda 函数引用了一个插件对象,在您的事件发生之前,该对象实际上不会被评估。当您的事件发生时,这部分代码将早已执行完毕,您将触发的实际插件将是最后遇到的一个。

“捕获”您想要的实际插件实例的一种方法是在 lambda 定义中捕获它,将其作为额外参数传递:

for plugin in self.pluginManager.plugins:
    wxId = wx.NewId()
    plugin_submenu.Append(wxID,plugin.displayName)
    canvas.Bind(wx.EVT_MENU, lambda evt, p=plugin, temp=objArgs:    
                p.performAction(evt,temp))

不确定我是否很好地解释了为什么/如何发生这种情况,但是 here是另一种可能有帮助的解释。

关于python - 在 wxPython 中,如何绑定(bind)到循环中的单独对象(包括参数)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25393119/

相关文章:

python - 为什么在Python中的这段代码中打印(len(list(nums))两次有不同的结果?

python - 来自 Process 的简单 wxPython post 事件

python - 对话框中的 wx.DatePickerCtrl 忽略在 wxGTK 上按回车键后输入的值

python - wxPython按钮加载多个图像

Python Django 相当于 Elixir Ecto 中的预加载

python - 如何将 pandas.to_datetime 与 "strange"字符串格式一起使用

python - 可以(安全地)从 linux 上的自定义 python 安装中删除什么,以使其更小

c# - 表示数字序列的算法

button - 如何使用我自己的自定义按钮并使用 wxpython 进行设计

python - wxpython的列表控件中的删除