1

I am trying to embed a matplotlib graph on my tkinter window and using the following code as a basis before using it in my main code.

https://matplotlib.org/gallery/user_interfaces/embedding_in_tk_canvas_sgskip.html

If I run the code below, I get the following error:

AttributeError: '_tkinter.tkapp' object has no attribute 'TclError'

Code:

import matplotlib as mpl
import numpy as np
import sys
import tkinter as tk
import matplotlib.backends.tkagg as tkagg
from matplotlib.backends.backend_agg import FigureCanvasAgg


def draw_figure(canvas, figure, loc=(0, 0)):
    #Draw a matplotlib figure onto a Tk canvas. loc: location of top-left corner of figure on canvas in pixels. Inspired by matplotlib source: lib/matplotlib/backends/backend_tkagg.py

    figure_canvas_agg = FigureCanvasAgg(figure)
    figure_canvas_agg.draw()
    figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
    figure_w, figure_h = int(figure_w), int(figure_h)
    photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)

    # Position: convert from top-left anchor to center anchor
    canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)

    # Unfortunately, there's no accessor for the pointer to the native renderer
    tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)

    # Return a handle which contains a reference to the photo object
    # which must be kept live or else the picture disappears
    return photo

# Create a canvas
w, h = 300, 200
window = tk.Tk()
window.title("A figure in a canvas")
canvas = tk.Canvas(window, width=w, height=h)
canvas.pack()

# Generate some example data
X = np.linspace(0, 2 * np.pi, 50)
Y = np.sin(X)

# Create the figure we desire to add to an existing canvas
fig = mpl.figure.Figure(figsize=(2, 1))
ax = fig.add_axes([0, 0, 1, 1])
ax.plot(X, Y)

# Keep this handle alive, or else figure will disappear
fig_x, fig_y = 100, 100
fig_photo = draw_figure(canvas, fig, loc=(fig_x, fig_y))
fig_w, fig_h = fig_photo.width(), fig_photo.height()

# Add more elements to the canvas, potentially on top of the figure
canvas.create_line(200, 50, fig_x + fig_w / 2, fig_y + fig_h / 2)
canvas.create_text(200, 50, text="Zero-crossing", anchor="s")

# Let Tk take over
tk.mainloop()

Can someone please help me resolve this error? I have found similar questions on Stack Overflow, however, for different attributes ('choice', getitems', 'text', 'PassCheck', etc.). Thanks.

1
  • Please don't forget to upvote :D Commented Dec 24, 2019 at 11:27

1 Answer 1

4

Replace import matplotlib as mpl with:

from matplotlib.figure import Figure

Then replace import matplotlib.backends.tkagg as tkagg with

from matplotlib.backends import _backend_tk

Finally, replace the line:

tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)

with:

_backend_tk.blit(
    photo, figure_canvas_agg.get_renderer()._renderer, (0, 1, 2, 3))

See if it works. You may want to reference this merge request: https://github.com/matplotlib/matplotlib/pull/11507/commits/9dfd6118f221ace2a3e0c8f43ef3e2e37186fa15

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, it worked. I kept import matplotlib as mpl since I use mpl later on.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.