Issue
There are plenty of web examples (1,2,3,4) and threads (1,2,3) about imbedding a plot into a tkinter window, but very few that address plotting in a separate environment and importing the resulting graph to the tkinter window.
In a nutshell, I have a program that calculates many different values, and exports those values to a separate file that creates a large number of plots. My tkinter application accepts parameters in Entry boxes, before applying them to the main file that does all the calculations. Typically, I would just follow the examples I linked, but with such a large number of plots being generated and the need to be able to select any particular graph I need at a given time, this would be inefficient and time consuming to brute-force. There must be a better way!
Below is a simplified example of how I am trying to accomplish this task:
import tkinter as tk
from matplotlib import pyplot as plt
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg,
NavigationToolbar2Tk)
import numpy as np
def example_plot(A):
# Plot generated outside of tkinter environment, but controlled by
# variable within tkinter window.
x = np.linspace(0, 10, 50)
y = A*x**2
fig, ax = plt.subplots()
ax.plot(x,y)
ax.set_xlabel('x')
ax.set_ylabel('y')
return fig
window = tk.Tk()
window.geometry('256x256')
variableEntry = tk.Entry(width = 10)
variableLabel = tk.Label(window, text = "A")
variableEntry.grid(row = 0, column = 0)
variableLabel.grid(row = 0, column = 1)
def plotButton():
A = variableEntry.get()
A = int(A)
figure = Figure(figsize = (1,1), dpi = 128)
add = figure.add_subplot(1,1,1)
example = example_plot(A)
add.imshow(example)
canvas = FigureCanvasTkAgg(figure)
canvas.get_tk_widget().grid(row = 2, column = 0)
toolbar = NavigationToolbar2Tk(canvas)
toolbar.update()
canvas._tkcanvas.grid(row = 3 , column = 0)
canvas.show()
applyButton = tk.Button(master = window, text = "Apply", command = plotButton)
applyButton.grid(row = 1,column = 0)
window.mainloop()
When I run this, set A to some integer and press apply, I get an error
TypeError: Image data of dtype object cannot be converted to float
It seems that add.imshow()
doesn't like that I fed it the figure. Is there some way to obtain the figure (ie: example = example_plot(A)
) and store it to display later?
Solution
Try this:
import tkinter as tk
from matplotlib import pyplot as plt
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, \
NavigationToolbar2Tk
import numpy as np
def example_plot(A):
# Plot generated outside of tkinter environment, but controlled by
# variable within tkinter window.
x = np.linspace(0, 10, 50)
y = A*x*x # This should run slightly faster
fig, ax = plt.subplots()
ax.plot(x,y)
ax.set_xlabel("x")
ax.set_ylabel("y")
return fig
window = tk.Tk()
frame = tk.Frame(window)
frame.pack()
variable_entry = tk.Entry(frame, width=10)
variable_label = tk.Label(frame, text="A")
variable_entry.pack(side="left", fill="x")
variable_label.pack(side="left")
def plot():
A = int(variable_entry.get())
figure = Figure(figsize=(1, 1), dpi=128)
add = figure.add_subplot(1, 1, 1)
figure = example_plot(A)
canvas = FigureCanvasTkAgg(figure)
canvas.get_tk_widget().pack()
toolbar = NavigationToolbar2Tk(canvas, window)
toolbar.update()
canvas.get_tk_widget().pack()
# canvas.show() # There is no need for this
apply_button = tk.Button(window, text="Apply", command=plot)
apply_button.pack(fill="x")
window.mainloop()
Your example_plot
returns a Figure
so you can use figure = example_plot(A)
and then FigureCanvasTkAgg(figure)
. I also added a frame and tried to make everything look better.
Answered By - TheLizzard
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.