问题描述
我目前正在从 wxPython 4.0.7 迁移到 wxPython 4.1.0。这将 wx 版本从 3.0.x 更改为 3.1.x。
Tl;博士:
使用 wx.ListCtrl
在 event.Skip()
事件处理程序中调用 wxEVT_SIZE
时,有时会出错。去Skip()
还是不去Skip()
? (即 wxEVT_SIZE
的默认事件处理是什么,我需要它吗?)
长版:
在 wx.ListCtrl
处理程序中使用 event.Skip
和 wxEVT_SIZE
会在我的某些表单中产生错误(所以我认为肯定还有更多)。现在,我无法将任何出现的情况删除为一个最小的例子,因为当我删除(看似)不相关的代码部分时,错误会随机消失。当我用较短的标签替换长标签时,错误甚至会消失(有时)。但是,更改框架或面板大小不会改变任何内容。
这是我发现的:
- 该错误肯定与
wx.ListCtrl
类的使用有关 - 错误仅在函数绑定到
wxEVT_COMMAND_LIST_ITEM_ACTIVATED
事件时发生,尽管空处理程序(带或不带Skip()
)足以引发错误。 - 该错误仅在函数绑定到
wxEVT_SIZE
事件时发生 - 该错误仅在我在
event.Skip()
处理程序中调用wxEVT_SIZE
时发生
似乎我可以简单地删除 event.Skip()
处理程序中的 wxEVT_SIZE
调用并完成,但相关的 C++ 代码似乎还有更多内容。
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()
时才能触发此断言,但跳过该事件,即假装该事件根本没有被处理。在理想的世界中,这应该是可能的,我认为断言实际上过于急切,需要放松,但现在,如果你真的需要这样做,你必须:
- 使用
Bind()
推迟呼叫CallAfter()
。 - 或者避免调用
event.Skip()
。
(请注意,在这种情况下不会总是触发断言,您还需要删除之前不久之前连接到同一对象的处理程序)。
但一般来说,您应该调用 Skip()
除非您已经完全处理了事件并且不希望任何其他处理程序,无论是基类中的还是内置的,都在您之后运行。对于 wxEVT_SIZE
,这意味着您已经自己重新布局了窗口,并且不希望基类做任何事情。因此,解决方案 (1) 更好,因为即使您确实希望运行基类处理程序,它也可以使用。