2

I have scoured the web for creating a live matplotlib scatter plot within a tkinter window but have found copious amounts of varying information making it confusing to decipher.As an example, I sometimes see some people use matplotlib.pyplot and I sometimes see some people use matplotlib.figure. I have no idea what the real differences between these two modules are.

I have created the example code below which I thought should simply create a matplotlib scatter plot inside the tkinter root window when I click the "Graph It" button. It does nothing when I click it though. The ultimate goal is to have a scatter plot within tkinter that updates whenever new data is read from a sensor but I'm starting simple. It should also be noted this is my first exposure to matplotlib so it may be something trivial I'm overlooking. Any help is appreciated.


#Python 3.7.9#
import tkinter as tk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg,NavigationToolbar2Tk)
import numpy as np




figure = Figure(figsize = (5,5), dpi = 100)
ax = figure.add_subplot(111)


def plot():
    

    x = np.random.rand(1,10)
    y = np.random.rand(1,10)
    
    ax.scatter(x,y)
 
    
 
    
root = tk.Tk()


canvas = FigureCanvasTkAgg(figure, root)
canvas.draw()
canvas.get_tk_widget().pack(pady = 10)

toolbar = NavigationToolbar2Tk(canvas,root)
toolbar.update()
canvas.get_tk_widget().pack()


button = tk.Button(root, text = "Graph It", command = plot)
button.pack()


root.mainloop()

EECE
  • 37
  • 2

1 Answers1

0

The problem lies in that you do not "update" the plot. With the minimal modification to your code, you just have to arrange to redraw the figure. For example, you can use your wrapper canvas object (or the figure.canvas) to update the figure's canvas in each data update step as follows:

import tkinter as tk

import numpy as np
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure

figure = Figure(figsize=(5, 5), dpi=100)
ax = figure.add_subplot(111)


def plot():
    x = np.random.rand(1, 10)
    y = np.random.rand(1, 10)
    ax.scatter(x, y)
    canvas.draw()


root = tk.Tk()
canvas = FigureCanvasTkAgg(figure, root)
canvas.draw()
canvas.get_tk_widget().pack(pady=10)
toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack()
button = tk.Button(root, text="Graph It", command=plot)
button.pack()
root.mainloop()

Output window:

enter image description here

However, in this case you add/create a new scatter plot in each update step. If you wish to extend the original data and update according to the updated data, you can find different methods in this post to update a single scatter plot.

czeni
  • 427
  • 2
  • 11
  • That did the trick! Thank you. I guess I'm a little confused about the "FigureCanvasTkAgg" class, is it a special class made just for adding matplotlib graphs to Tkinter windows? I looked at what I thought was documentation of the class methods for "FigureCanvasTkAgg" and I don't see a method called .get_tk_widget(). What is this method doing? Here is the [documentation](https://matplotlib.org/stable/api/backend_tk_api.html?highlight=figurecanvastkagg#matplotlib.backends.backend_tkagg.FigureCanvasTkAgg) I was looking at, – EECE Aug 03 '21 at 01:23
  • I assume `FigureCanvasTkAgg` is a wrapper that solves the integration between Tkinter and matplotlib, However, at first I tried to update directly the matplotlib's canvas with `figure.canvas.draw()` and it worked, as well. So I assume readrawing is performed with matploltib, and wigdet-related stuff is provided with the wrapper class. – czeni Aug 03 '21 at 09:38