Matplotlib figure.savefig() tkinter - python

I have embedded my matplotlib plot in tkinter according to http://matplotlib.org/examples/user_interfaces/embedding_in_tk2.html successfully, but I also want to save my plot. How do I do this? I tried figure.savefig (as below); I thought this would work from looking at http://matplotlib.org/api/figure_api.html:
#!/usr/bin/env python
import matplotlib
matplotlib.use('TkAgg')
from numpy import arange, sin, pi
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import sys
if sys.version_info[0] < 3:
import Tkinter as Tk
else:
import tkinter as Tk
def destroy(e): sys.exit()
root = Tk.Tk()
root.wm_title("Embedding in TK")
#root.bind("<Destroy>", destroy)
f = Figure(figsize=(5,4), dpi=100)
a = f.add_subplot(111)
t = arange(0.0,3.0,0.01)
s = sin(2*pi*t)
a.plot(t,s)
a.set_title('Tk embedding')
a.set_xlabel('X axis label')
a.set_ylabel('Y label')
f.savefig('hello.png')
# a tk.DrawingArea
canvas = FigureCanvasTkAgg(f, master=root)
canvas.show()
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
#toolbar = NavigationToolbar2TkAgg( canvas, root )
#toolbar.update()
canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
button = Tk.Button(master=root, text='Quit', command=sys.exit)
button.pack(side=Tk.BOTTOM)
Tk.mainloop()

The Figure needs a FigureCanvas to draw on. In other words, don't call savefig until after the FigureCanvas has been established:
# a tk.DrawingArea
canvas = FigureCanvasTkAgg(f, master=root)
canvas.show()
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
f.savefig('hello.png')

Related

Unable to embed networkx graph using matplotlib in customtk

I'm trying to embed a networkx graph in CustomTk, but the graph doesn't appear. When I use plt.show() I can see the graph in matplotlib pop-up menu, but not in GUI.
import tkinter
import customtkinter
import networkx as nx
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
# Implement the default Matplotlib key bindings.
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import numpy as np
root = customtkinter.CTk()
root.title("Embedding in Tk")
fig = Figure(figsize=(5, 4), dpi=100)
G = nx.random_geometric_graph(20, 0.125, seed=896803)
nx.draw_networkx(G, pos=nx.circular_layout(G), node_size=4000, with_labels=True, font_size=20)
plt.style.use('ggplot')
fig = Figure(figsize=(10, 10), dpi=100)
ax = fig.add_subplot(111)
ax = plt.gca()
ax.margins(0.11)
plt.tight_layout()
plt.axis("off")
canvas = FigureCanvasTkAgg(fig, master=root) # A tk.DrawingArea.
canvas.draw()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
plt.show()
def on_key_press(event):
print("you pressed {}".format(event.key))
key_press_handler(event, canvas, toolbar)
canvas.mpl_connect("key_press_event", on_key_press)
def _quit():
root.quit() # stops mainloop
root.destroy() # this is necessary on Windows to prevent
# Fatal Python Error: PyEval_RestoreThread: NULL tstate
button = customtkinter.CTkButton(master=root, text="Quit", command=_quit)
button.pack(side=tkinter.BOTTOM)
root.mainloop()
# If you put root.destroy() here, it will cause an error if the window is
# closed with the window manager.
plt.show() image:
figure on canvas:
I'm not sure what's the issue when drawing on the canvas.
Thanks in advance
Solution: https://github.com/TomSchimansky/CustomTkinter/issues/971#issuecomment-1371489896
import tkinter
import customtkinter
import networkx as nx
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
# Implement the default Matplotlib key bindings.
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import numpy as np
root = customtkinter.CTk()
root.title("Embedding in Tk")
#call fig ax exactly once
fig = Figure(figsize=(5, 4), dpi=100)
ax = fig.add_subplot(111)
ax.margins(0.11)
#call the graphing module
G = nx.random_geometric_graph(20, 0.125, seed=896803)
#draw the graph, note the ax=ax at the end, this is the critical part, matplotlib needs to know onto which axis the graph is drawn
#otherwise it will just draw it in the spyder backend, without a care for your other elements
nx.draw(G, pos=nx.circular_layout(G), node_size=4000, with_labels=True, font_size=20,ax=ax)
canvas = FigureCanvasTkAgg(fig, master=root) # A tk.DrawingArea.
canvas.draw()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
def _quit():
root.quit() # stops mainloop
root.destroy() # this is necessary on Windows to prevent
# Fatal Python Error: PyEval_RestoreThread: NULL tstate
button = customtkinter.CTkButton(master=root, text="Quit", command=_quit)
button.pack(side=tkinter.BOTTOM)
root.mainloop()
# If you put root.destroy() here, it will cause an error if the window is
# closed with the window manager.

matplotlib add to panedwindow in tkinter

I do not understand how correctly add matplotlib into panedwindow of tkinter.
I want to have on one side list box and matplotlib interactive plot, on the other side
I need to resize listbox and plot by dragging boundary between them
this is what is desirable
I tried this but I cannot add correctly matplot lib to paned window
from tkinter import *
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
# Implement the default Matplotlib key bindings.
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import numpy as np
root = Tk()
m = PanedWindow(root)
m.pack(fill=BOTH, expand=1)
fig = Figure(figsize=(5, 4), dpi=100)
t = np.arange(0, 3, .01)
fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t))
canvas = FigureCanvasTkAgg(fig, master = root) # A tk.DrawingArea.
canvas.draw()
canvas.get_tk_widget().pack(side=RIGHT, fill=BOTH, expand=1)
toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=RIGHT, fill=BOTH, expand=1)
m.add(toolbar)
m.add(canvas)
lstbox2 = Listbox(selectmode=MULTIPLE, width=20, height=10)
m.add(lstbox2)
root.mainloop()
Put your canvas and toolbar in a Frame instead, and add that Frame to your paned window:
root = Tk()
...
canvas_frame = Frame(root)
canvas = FigureCanvasTkAgg(fig, master = canvas_frame)
canvas.draw()
canvas.get_tk_widget().pack()
toolbar = NavigationToolbar2Tk(canvas, canvas_frame)
toolbar.update()
toolbar.pack_configure(expand=True)
m.add(canvas_frame)
lstbox2 = Listbox(selectmode=MULTIPLE, width=20, height=10)
m.add(lstbox2)
root.mainloop()

How do you change the plot background color in a tkinter application?

I have a plot in a tkinter application and I am trying to change the background color of the plot using tkinter colors. I have found How to change plot background color? however, I got this error:
ValueError: Invalid RGBA argument: 'AntiqueWhite2'
...indicating I may only be able to use their subset of colors? Does anyone know how to use the tkinter colors here?
Here is what I am currently using (without color change):
self.fig = Figure(figsize=(5, 4), dpi=100)
self.canvas = FigureCanvasTkAgg(self.fig, master=self.master) # A tk.DrawingArea
self.canvas.draw()
self.ax = self.fig.add_subplot(111)
import tkinter
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
# Implement the default Matplotlib key bindings.
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
import numpy as np
root = tkinter.Tk()
root.geometry("770x633+745+171")
Frame1 = tkinter.Frame(root)
Frame1.place(relx=0.1, rely=0.1, relheight=0.3, relwidth=0.5)
root.wm_title("Embedding in Tk")
t = np.arange(0, 3, .01)
fig = Figure(figsize=(5, 3), dpi=80,facecolor = 'k')
axes1 =fig.add_subplot(111)
# axes1.axis('tight')
axes1.autoscale(enable=True, axis='y', tight=True)
axes1.plot(t, 2 * np.sin(2 * np.pi * t))
# axes1.set_axis_bgcolor('k')
axes1.set_facecolor('k')
axes1.grid(color = 'w')
for label in axes1.xaxis.get_ticklabels():
# label is a Text instance
label.set_color('w')
for label in axes1.yaxis.get_ticklabels():
# label is a Text instance
label.set_color('w')
# label.set_rotation(45)
# label.set_fontsize(1)
for line in axes1.yaxis.get_ticklines():
# line is a Line2D instance
line.set_color('w')
for line in axes1.xaxis.get_ticklines():
# line is a Line2D instance
line.set_color('w')
# line.set_markersize(25)
# line.set_markeredgewidth(3)
for line in axes1.xaxis.get_gridlines():
line.set_color('w')
for line in axes1.yaxis.get_gridlines():
line.set_color('w')
line.set_markeredgewidth(8)
axes1.yaxis.grid(color='w',linewidth=1)
# axes1.set_xmargin(0.9)
axes1.set_xlabel("Time(ns)")
axes1.xaxis.label.set_color('w')
axes1.set_ylabel("Amplitude(mV)")
axes1.yaxis.label.set_color('w')
axes1.xaxis.grid(color='w',linewidth=1)
axes1.spines['bottom'].set_color('white')
axes1.spines['top'].set_color('white')
axes1.spines['left'].set_color('white')
axes1.spines['right'].set_color('white')
canvas = FigureCanvasTkAgg(fig, master=Frame1) # A tk.DrawingArea.
canvas.get_tk_widget().configure(bg='black')
canvas.get_tk_widget().grid(row=1,column=0)
canvas.get_tk_widget().grid(row=1,column=0)
# canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
canvas.draw()
toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
def on_key_press(event):
print("you pressed {}".format(event.key))
key_press_handler(event, canvas, toolbar)
canvas.mpl_connect("key_press_event", on_key_press)
fig.tight_layout()
def _quit():
root.quit() # stops mainloop
root.destroy() # this is necessary on Windows to prevent
# Fatal Python Error: PyEval_RestoreThread: NULL tstate
button = tkinter.Button(master=root, text="Quit", command=_quit)
button.pack(side=tkinter.BOTTOM)
tkinter.mainloop()
# plt.tight_layout()
This is an example for change the background as black and change the label, grid, tick labels, ... color.

How to realise matplotlib line picker by using opencv?

I would like to pick lines that have been drawn on an image by using cv2.line and do something with them. To realise that I had a look on matplotlibs picker and even found a good example here. As I am going to use tkinter for GUI I added it to my MWE.
Code from example which works fine:
import sys
if sys.version_info[0] < 3:
import Tkinter as Tk
else:
import tkinter as Tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
import numpy as np
root = Tk.Tk()
root.iconify()
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots()
for i in range(1, 10):
ax.plot(x, i * x + x, picker=5)
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
def on_pick(event):
event.artist.set_visible(not event.artist.get_visible())
fig.canvas.draw()
fig.canvas.callbacks.connect('pick_event', on_pick)
root.mainloop()
Now my code using OpenCV which does not work:
import sys
if sys.version_info[0] < 3:
import Tkinter as Tk
else:
import tkinter as Tk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
import cv2
root = Tk.Tk()
root.iconify()
img = np.zeros([100,100,3],dtype=np.uint8)
img.fill(255)
cv2.line(img,(10,10),(60,90),(100,149,237),2)
fig = Figure()
ax = fig.add_subplot(111)
ax.set_aspect('equal')
ax.plot()
ax.imshow(img)
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
def onpick1(event):
event.artist.set_visible(not event.artist.get_visible())
fig.canvas.draw()
fig.canvas.callbacks.connect('pick_event', onpick1)
root.mainloop()
In both examples onpick1 should set the lines visibility on or off by a single mouse click but it doesn't. My assumption is that it has something to do with the way it is plotted or how I draw the lines (ax.plt vs cv2.line). I would be very happy about any help. Thanks!

Overlay graph in tkinter

I am making an embeded matplotlib graph GUI program.
I want to make overlaid graphs in upper graph window when users click the "Update" button.
But, There is no response when I click "Update" button.
I am using Spyder Python 3.6 Version.
Below is what I wrote.
import matplotlib.pyplot as plt
import csv
import numpy as np
import tkinter as tk
from tkinter import ttk
import matplotlib as plt
plt.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
from matplotlib import style
class Analysis_app(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
tk.Tk.wm_title(self, "SIM Analyser")
right_f = tk.Frame(self)
right_f.pack(side=tk.RIGHT)
self.entry1 = ttk.Entry(right_f).pack()
self.entry2 = ttk.Entry(right_f).pack()
self.entry3 = ttk.Entry(right_f).pack()
self.entry4 = ttk.Entry(right_f).pack()
self.entry5 = ttk.Entry(right_f).pack()
Button1 = ttk.Button(right_f, text='Update', command=self.plot).pack(side=tk.BOTTOM)
self.left_f = tk.Frame(self)
self.left_f.pack(side=tk.LEFT)
f = Figure(figsize=(10,6), dpi=100)
self.upplot = f.add_subplot(211)
self.botplot = f.add_subplot(212)
a =self.upplot
a.clear()
a.plot([1,2,3],[1,2,3])
canvas = FigureCanvasTkAgg(f, self)
canvas.show()
canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
toolbar = NavigationToolbar2TkAgg(canvas, self)
toolbar.update()
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
self.mainloop()
def plot(self):
a =self.upplot
a.clear()
a.plot([1,2,3],[5,2,5])
You get no response because the canvas is not redrawn after changing the content of the plot.
The solution is to replace canvas = FigureCanvasTkAgg(f, self) by self.canvas = FigureCanvasTkAgg(f, self) so that you can redraw the canvas in self.plot:
def plot(self):
a = self.upplot
a.clear()
a.plot([1,2,3],[5,2,5])
self.canvas.draw_idle()
And then you should see the change after clicking on the update button.

Categories