Matplotlib嵌入wxPython后,替代fig.canvas.get_tk_widget().update()的方法
When working with Matplotlib embedded in wxPython, you can't rely on TkAgg-specific methods like get_tk_widget().update()—instead, you need to work with wxPython's event-driven model and the FigureCanvasWxAgg widget directly. Here's how to replicate your desired pause/click behavior properly:
Key Differences from TkAgg
wxPython uses an event loop (app.MainLoop()) instead of a manual while True loop, so we'll use a wx.Timer to handle periodic plot updates without blocking the UI. To refresh the canvas, we'll combine Matplotlib's rendering with wx's widget refresh methods.
Complete Example Code
import wx import matplotlib.pyplot as plt import numpy as np from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar class MatplotlibWxFrame(wx.Frame): def __init__(self, parent, title="wxMatplotlib Pause Demo"): super().__init__(parent, title=title, size=(800, 600)) # Initialize Matplotlib figure and canvas self.fig, self.ax = plt.subplots() self.canvas = FigureCanvas(self, -1, self.fig) self.toolbar = NavigationToolbar(self.canvas) # Layout setup main_sizer = wx.BoxSizer(wx.VERTICAL) main_sizer.Add(self.canvas, 1, wx.EXPAND | wx.ALL, 5) main_sizer.Add(self.toolbar, 0, wx.EXPAND | wx.ALL, 5) self.SetSizer(main_sizer) # Pause state flag self.pause = False # Bind Matplotlib's click event self.fig.canvas.mpl_connect('button_press_event', self.on_canvas_click) # Set up timer for periodic plot updates (100ms interval) self.update_timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.update_plot_content, self.update_timer) self.update_timer.Start(100) def on_canvas_click(self, event): # Toggle pause state when the canvas is clicked self.pause = not self.pause print(f"Pause toggled: {'Paused' if self.pause else 'Resumed'}") def update_plot_content(self, event): if not self.pause: # Your custom plotting logic goes here self.ax.clear() # Example: Plot a shifting sine wave x = np.linspace(0, 10, 200) y = np.sin(x + np.random.rand() * 2 * np.pi) self.ax.plot(x, y, linewidth=2) self.ax.set_title("Click canvas to pause/resume") # Refresh the plot: first let Matplotlib render, then update wx widget self.fig.canvas.draw() self.canvas.Refresh() # Triggers wx to redraw the canvas widget if __name__ == "__main__": app = wx.App(False) frame = MatplotlibWxFrame(None) frame.Show() app.MainLoop()
Breakdown of Critical Parts
- Event-Driven Updates: Instead of a
while Trueloop, we usewx.Timerto trigger plot updates at regular intervals. This keeps the wx event loop running so the UI remains responsive (no frozen windows or unclickable elements). - Canvas Refresh:
self.fig.canvas.draw(): Tells Matplotlib to re-render the figure with new data.self.canvas.Refresh(): Asks wxPython to update theFigureCanvasWxAggwidget on screen—this directly replaces the TkAggget_tk_widget().update()call.
- Pause Toggle: The
button_press_eventbinding works identically to the TkAgg version, but we toggle a flag that controls whether the timer's update logic executes.
Why Avoid Manual Loops?
A while True loop in wxPython would block the main event loop, making your window unresponsive (you wouldn't be able to click buttons, resize, or close the window). Using timers fits naturally with wx's event model and keeps everything running smoothly.
内容的提问来源于stack exchange,提问作者David

