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