集成SFML的wxWidgets窗口关闭崩溃,求解决方法
问题
在wxWidgets框架中集成SFML视图,基于SFML官网旧示例修改开发项目,需动态创建销毁多个SFML+wxWidgets窗口,但关闭父wxWidgets窗口时SFML崩溃,报错:
Cannot close SFML area when SFML is integrated in a NSView.
所有公开的SFML+wxWidgets示例均存在该问题,单次关闭影响有限,但多窗口会话中崩溃会导致整个应用挂掉。
相关基类代码:
class ChessWidgetBase : public wxControl, public sf::RenderWindow { public: ChessWidgetBase(wxWindow* parent, wxSize size); virtual ~ChessWidgetBase() {}; private: DECLARE_EVENT_TABLE() virtual void HandleLeftDown(wxMouseEvent&) {} virtual void HandleLeftUp(wxMouseEvent&) {} virtual void OnUpdate() {}; void OnIdle(wxIdleEvent&); void OnPaint(wxPaintEvent&); void OnEraseBackground(wxEraseEvent&); };
解决方案
核心思路是在SFML RenderWindow被销毁前,主动解除它与wxWidgets控件的关联,避免SFML尝试关闭已被wxWidgets回收的原生窗口资源。
具体实现步骤
- 重写SFML画布基类的析构函数,确保SFML窗口先于wxWidgets控件关闭
- 拦截父窗口的关闭事件,提前手动销毁所有SFML画布实例,再执行窗口关闭流程
代码示例
1. 修改ChessWidgetBase的析构函数
virtual ~ChessWidgetBase() { // 先关闭SFML RenderWindow,解除与原生窗口的绑定 if (isOpen()) { close(); } };
2. 在父窗口类中拦截关闭事件
以AppFrame为例,添加关闭事件处理函数:
void OnClose(wxCloseEvent& event) { // 手动销毁SFML画布实例(使用智能指针时直接重置即可) _canvas.reset(); // 继续执行窗口关闭流程 event.Skip(); }
并在AppFrame构造函数中绑定该事件:
Bind(wxEVT_CLOSE_WINDOW, &AppFrame::OnClose, this);
额外注意事项
- 对于动态创建的多个SFML画布,需维护实例列表,在父窗口关闭时遍历销毁所有实例
- macOS平台下SFML对NSView生命周期管理更严格,必须保证SFML窗口先于原生视图释放
内容的提问来源于stack exchange,提问作者Crupeng
相关产品推荐
相关产品推荐

