使用WxPython时plt.pause(0.1)弹出双窗口,如何合并至单窗口?
解决WxPython中
plt.pause弹出额外Figure窗口的问题 我完全懂你遇到的糟心情况——明明已经用了WxPython做程序框架,结果调用plt.pause(0.1)时,Matplotlib非要额外弹出一个独立的Figure窗口,两个窗口共存的样子完全不符合预期。
问题出在你还在依赖Matplotlib的全局plt上下文,哪怕指定了WXAgg后端,直接调用plt的方法还是会默认创建独立的Figure容器。要把动态渲染效果完全嵌入Wx窗口,得把Matplotlib的画布直接作为Wx控件来用,具体方案如下:
# -*-coding:utf-8-*- import wx import matplotlib # 必须在导入pyplot或cartopy前设置Wx后端 matplotlib.use('WXAgg') from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg from matplotlib.figure import Figure import cartopy.crs as ccrs import matplotlib.ticker as mticker class WxMatplotlibFrame(wx.Frame): def __init__(self, parent, title): super().__init__(parent, title=title, size=(800, 600)) # 1. 创建独立的Matplotlib Figure对象,不依赖plt全局上下文 self.figure = Figure(figsize=(8, 6), dpi=100) # 2. 添加带cartopy投影的子图 self.ax = self.figure.add_subplot(111, projection=ccrs.PlateCarree()) # 初始化cartopy地图元素 self.ax.coastlines() gl = self.ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=1, color='gray', alpha=0.5, linestyle='--') gl.top_labels = gl.right_labels = False gl.xlocator = mticker.FixedLocator([-180, -90, 0, 90, 180]) gl.ylocator = mticker.FixedLocator([-90, -45, 0, 45, 90]) # 3. 把Figure包装成Wx控件,嵌入到窗口布局里 self.canvas = FigureCanvasWxAgg(self, -1, self.figure) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.canvas, 1, wx.EXPAND) self.SetSizer(sizer) # 启动动态更新逻辑(替代plt.pause的场景) self.start_dynamic_update() def start_dynamic_update(self): # 这里写你的动态更新逻辑,比如实时修改图形元素 self.ax.scatter(0, 0, color='red', transform=ccrs.PlateCarree()) # 替代plt.pause的核心操作: self.canvas.draw() # 刷新画布 wx.Yield() # 让Wx处理事件循环,避免界面卡顿 wx.MilliSleep(100) # 对应plt.pause(0.1)的100毫秒暂停 # 如果需要循环更新,用Wx的定时器而非死循环,保证界面响应 wx.CallLater(100, self.start_dynamic_update) if __name__ == '__main__': app = wx.App(False) frame = WxMatplotlibFrame(None, "Matplotlib嵌入WxPython示例") frame.Show() app.MainLoop()
关键注意点:
- 抛弃plt全局上下文:直接创建
Figure对象,通过FigureCanvasWxAgg转为Wx控件,这样图形完全属于你的Wx框架,不会再弹出独立窗口。 - 替换
plt.pause:plt.pause本质是刷新图形+处理事件循环,在Wx环境下用canvas.draw()+wx.Yield()+wx.MilliSleep()组合实现,效果一致且不触发额外窗口。 - 后端设置时机:
matplotlib.use('WXAgg')必须在导入plt或cartopy之前执行,否则后端设置不会生效。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

