0

I want to put a matplotlib figure in a tkinter user interface. This is my code, based on the matplotlib documentation:

import tkinter as tk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import sys

root = tk.Tk()

fig = plt.figure(figsize=(4,4))
ax = fig.add_subplot()
line, = ax.plot([1,2,3],[1,4,9])

canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()

toolbar = NavigationToolbar2Tk(canvas, root, pack_toolbar=False)
toolbar.update()

canvas.get_tk_widget().pack()
toolbar.pack()

tk.Button(root, text="Exit", command=lambda:sys.exit()).pack()

root.mainloop()

I runs correctly. The problem comes when I close the window. If I press the "X" button of the window, the terminal never finishes, but if I press the "Exit" button I added, it finishes. If instead I use root.destroy(), it neither works. How can I solve this issue?

Thanks!

Edit:

I uploaded a video in YouTube, so you can see my problem: https://youtu.be/qUkm-lnXRR8

I'm using Windows 11 PowerShell, version:

Name                           Value
----                           -----
PSVersion                      5.1.22621.963
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.22621.963
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Python version 3.11.1

  • It shouldn't have that behaviour. How do you run it in the terminal? What OS are you using? Can't reproduce the problem on Ubuntu. – TheLizzard Jan 01 '23 at 20:11
  • @TheLizzard see the edit above – Abel Gutiérrez Jan 03 '23 at 13:58
  • Add a print statement after the `mainloop()`. Does the print statement get called? A temporary work around would be to use [this](https://stackoverflow.com/a/4643082/11106801) – TheLizzard Jan 03 '23 at 14:02
  • @TheLizzard the print statement after the `mainloop` is never printed. Following the accepted answer on the question you shared, I can use `root.protocol("WM_DELETE_WINDOW", lambda: sys.exit())` and it works. But this cannot be the "final" solution because therefore I cannot run any code after the mainloop is finished. – Abel Gutiérrez Jan 03 '23 at 15:25
  • instead of `lambda:sys.exit()`, have a function with the code that you want to run after the GUI is closed and make sure the function ends with `sys.exit()`. But that is a work around. For a proper solution, someone needs to look at `matplotlib`'s code and maybe file a bug report. – TheLizzard Jan 03 '23 at 15:27
  • Thanks for your comments @TheLizzard , I will report this bug. – Abel Gutiérrez Jan 03 '23 at 15:32
  • You can track this issue at https://github.com/matplotlib/matplotlib/issues/24874 – Abel Gutiérrez Jan 03 '23 at 16:18

1 Answers1

0

Following this GitHub issue, this solves the issue

import tkinter as tk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import sys
from matplotlib.figure import Figure #### This is the difference

root = tk.Tk()

fig = Figure() # plt.figure()
ax = fig.add_subplot()

canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()

toolbar = NavigationToolbar2Tk(canvas, root, pack_toolbar=False)
toolbar.update()

canvas.get_tk_widget().pack()
toolbar.pack()

tk.Button(root, text="Exit", command=lambda:sys.exit()).pack()

root.mainloop()

print("Hello")
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 04 '23 at 15:30