wxPython 从 4.0.7 迁移到 4.1.0:事件处理时出现 ListCtrl 错误

问题描述

我目前正在从 wxPython 4.0.7 迁移到 wxPython 4.1.0。这将 wx 版本从 3.0.x 更改为 3.1.x。

Tl;博士: 使用 wx.ListCtrlevent.Skip() 事件处理程序中调用 wxEVT_SIZE 时,有时会出错。去Skip()还是不去Skip()? (即 wxEVT_SIZE认事件处理是什么,我需要它吗?)


长版:

wx.ListCtrl 处理程序中使用 event.SkipwxEVT_SIZE 会在我的某些表单中产生错误(所以我认为肯定还有更多)。现在,我无法将任何出现的情况删除一个最小的例子,因为当我删除(看似)不相关的代码部分时,错误随机消失。当我用较短的标签替换长标签时,错误甚至会消失(有时)。但是,更改框架或面板大小不会改变任何内容

这是我发现的:

  • 错误肯定与 wx.ListCtrl 类的使用有关
  • 错误仅在函数绑定到 wxEVT_COMMAND_LIST_ITEM_ACTIVATED 事件时发生,尽管空处理程序(带或不带 Skip())足以引发错误
  • 错误仅在函数绑定到 wxEVT_SIZE 事件时发生
  • 错误仅在我在 event.Skip() 处理程序中调用 wxEVT_SIZE 时发生

似乎我可以简单地删除 event.Skip() 处理程序中的 wxEVT_SIZE 调用并完成,但相关的 C++ 代码似乎还有更多内容

这里是错误(注意:错误不会使 wxApp 崩溃):

wx._core.wxAssertionError: C++ assertion "nNew != dynamicEvents.size()" Failed at ..\..\src\common\event.cpp(1926) in wxEvtHandler::SearchDynamicEventTable():

The above exception was the direct cause of the following exception:

SystemError: <class 'wx._core.SizeEvent'> returned a result with an error set

github 存储库中的相关 C++ 代码可以在这里找到:https://github.com/wxWidgets/wxWidgets/blob/e803408058186a7a9a61c456246f145abcaccd13/src/common/event.cpp#L1926

提示:这是 wxPython 4.1.0 版本中使用的固定 wxWidget 版本)

这里的任何 wx 和 C++ 专家,可能知道发生了什么?

解决方法

我相信只有当处理程序从其事件处理程序调用 Bind() 时才能触发此断言,但跳过该事件,即假装该事件根本没有被处理。在理想的世界中,这应该是可能的,我认为断言实际上过于急切,需要放松,但现在,如果你真的需要这样做,你必须:

  1. 使用 Bind() 推迟呼叫 CallAfter()
  2. 或者避免调用event.Skip()

(请注意,在这种情况下不会总是触发断言,您还需要删除之前不久之前连接到同一对象的处理程序)。

但一般来说,您应该调用 Skip() 除非您已经完全处理了事件并且不希望任何其他处理程序,无论是基类中的还是内置的,都在您之后运行。对于 wxEVT_SIZE,这意味着您已经自己重新布局了窗口,并且不希望基类做任何事情。因此,解决方案 (1) 更好,因为即使您确实希望运行基类处理程序,它也可以使用。