Of course! Let's dive deep into FigureCanvas in Python. This is a fundamental concept in Matplotlib, and understanding it is key to creating custom and interactive applications.

What is FigureCanvas?
At its core, FigureCanvas is the bridge between your Matplotlib Figure (the high-level container for all plot elements) and a specific backend (the renderer that actually draws the figure on a screen or to a file).
Think of it like this:
Figure: The artist's blueprint. It defines the layout, axes, labels, and plots.FigureCanvas: The physical canvas the artist paints on. It takes the blueprint and renders it.Renderer: The artist's brushes and paints. It's the low-level drawing engine that knows how to put pixels on the canvas.
The FigureCanvas class is responsible for:
- Managing the drawing surface (e.g., a window in Qt, a Tkinter widget, or a file).
- Handling events like mouse clicks and key presses, which is crucial for interactivity.
- Providing the methods to actually draw the figure (
draw()) and redraw parts of it (blit()).
Why Use FigureCanvas Directly?
You might be thinking, "I've never used FigureCanvas before, and my plots work fine!" That's because when you use the standard matplotlib.pyplot interface (plt.plot()), it automatically creates a Figure and a FigureCanvas for you behind the scenes.

You need to use FigureCanvas directly when you want to:
- Embed plots into a GUI framework like PyQt/PySide, Tkinter, or WxPython. This is the most common use case.
- Create highly interactive applications where you need to manually handle events (e.g., clicking on a plot to change its data).
- Write a custom application with a specific UI layout that isn't just a single plot window.
- Gain fine-grained control over the rendering process.
Key Components and Workflow
To use FigureCanvas, you'll typically work with three main classes from a specific backend:
FigureCanvas: The widget that holds the plot.Figure: The container for the plot(s).NavigationToolbar2Tk(or similar): The toolbar with pan, zoom, and save buttons.
The general workflow is:
- Import the necessary classes from your chosen backend (e.g.,
matplotlib.backends.backend_tkagg). - Create a
Figureobject. - Create a
FigureCanvasobject, passing it theFigure. - Create a
NavigationToolbarobject, also passing it theFigureCanvas. - Add the canvas and toolbar to your GUI window.
Practical Example: Embedding in Tkinter
Let's create a simple Tkinter application that displays a Matplotlib plot. This is the most illustrative example.

Step 1: Install Tkinter (if not already installed) Tkinter usually comes pre-installed with Python. If not, you can install it:
# On Ubuntu/Debian sudo apt-get install python3-tk # On macOS (if using Homebrew Python) brew install python-tk # On Windows, it's usually included with the Python installer
Step 2: Write the Python Code
Here is a complete, runnable script.
import tkinter as tk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
# --- 1. Create the main window ---
root = tk.Tk()"Matplotlib in Tkinter")
root.geometry("800x600")
# --- 2. Create a Matplotlib Figure ---
# This is the "blueprint" for our plot.
fig = Figure(figsize=(7, 5), dpi=100)
# Add a subplot to the figure
ax = fig.add_subplot(111) # 111 means 1 row, 1 column, 1st subplot
# Plot some data on the subplot
ax.plot([1, 2, 3, 4, 5], [1, 4, 2, 3, 5])
ax.set_title("Simple Plot")
ax.set_xlabel("X-axis")
ax.set_ylabel("Y-axis")
ax.grid(True)
# --- 3. Create the FigureCanvasTkAgg ---
# This is the bridge, the "canvas" that will display our figure in Tkinter.
# We pass the Figure object to it.
canvas = FigureCanvasTkAgg(fig, master=root)
# The `get_tk_widget()` method returns a Tkinter widget that can be placed in the window.
canvas_widget = canvas.get_tk_widget()
# Pack the canvas widget to make it visible in the window
canvas_widget.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
# --- 4. Add the Navigation Toolbar ---
# This provides interactive features like pan, zoom, and reset.
toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
toolbar.pack(side=tk.TOP, fill=tk.X)
# --- 5. Add a button to update the plot ---
def update_plot():
"""Updates the plot with new random data."""
import random
ax.clear() # Clear the previous plot
new_data_x = [1, 2, 3, 4, 5]
new_data_y = [random.randint(1, 10) for _ in new_data_x]
ax.plot(new_data_x, new_data_y)
ax.set_title("Updated Plot")
ax.set_xlabel("X-axis")
ax.set_ylabel("Y-axis")
ax.grid(True)
# Redraw the canvas
canvas.draw()
update_button = tk.Button(master=root, text="Update Plot", command=update_plot)
update_button.pack(side=tk.BOTTOM, pady=10)
# --- 6. Run the application ---
root.mainloop()
Breakdown of the Code:
fig = Figure(...): We create a MatplotlibFigure. This is where our plot lives.ax = fig.add_subplot(...): We add anAxesobject to the figure. TheAxesis the actual plotting area with its own x and y axes.canvas = FigureCanvasTkAgg(fig, master=root): This is the key step. We instantiateFigureCanvasTkAgg, which is the Tkinter-specific implementation ofFigureCanvas. We tell it to use ourfigand embed it into our main Tkinterrootwindow.canvas_widget = canvas.get_tk_widget(): TheFigureCanvasTkAggobject is not a native Tkinter widget itself. This method wraps it in one that Tkinter can understand and manage.canvas.draw(): This method tells the canvas to render theFigureonto its drawing surface. You must call this (orcanvas.get_tk_widget().draw()) whenever you make changes to the plot (like clearing or re-plotting data).NavigationToolbar2Tk(...): This adds the familiar toolbar with icons for saving, panning, zooming, etc., making your application much more user-friendly.
Other GUI Frameworks
The pattern is very similar for other backends, you just swap out the import and the canvas class.
Example for PyQt/PySide
# pip install pyqt5
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
class MyMplCanvas(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
super(MyMplCanvas, self).__init__(fig)
self.setParent(parent)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Matplotlib in PyQt")
self.setGeometry(100, 100, 800, 600)
layout = QVBoxLayout()
# Create the custom Matplotlib canvas
self.mpl_canvas = MyMplCanvas(self, width=5, height=4, dpi=100)
self.mpl_canvas.axes.plot([0, 1, 2, 3, 4], [10, 1, 20, 3, 40])
layout.addWidget(self.mpl_canvas)
container = QWidget()
container.setLayout(layout)
self.setCentralWidget(container)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Summary
| Concept | Role | Analogy |
|---|---|---|
Figure |
High-level container for plots, axes, labels. | The artist's blueprint. |
Axes |
The actual plotting area with x/y limits, ticks, etc. | A specific room on the blueprint. |
FigureCanvas |
The backend-specific widget that renders the Figure. |
The physical canvas/paper. |
Renderer |
The low-level drawing engine. | The artist's paintbrush. |
pyplot |
A high-level interface that manages Figure and Canvas for you. |
The art gallery manager who handles everything. |
By understanding FigureCanvas, you move from being a simple user of Matplotlib to a developer who can integrate powerful visualizations into complex, custom applications.
