Overlay graph in tkinter - python

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.

Related

Rotate matplotlib NavigationToolbar2Tk to make it vertical

I have 3 plots like this in a Tkinter window
Is it possible to orient the NavigationToolbar2Tk vertically so I can place it on the left of the plot ?
I didn't find any documentation or thread about something similar.
Thanks
You need to create a derived class from NavigationToolbar2Tk to override the default horizontal orientation.
Below is an example (based on the "Embedding in Tk" example):
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
import numpy as np
class VerticalNavigationToolbar2Tk(NavigationToolbar2Tk):
def __init__(self, canvas, window):
super().__init__(canvas, window, pack_toolbar=False)
# override _Button() to re-pack the toolbar button in vertical direction
def _Button(self, text, image_file, toggle, command):
b = super()._Button(text, image_file, toggle, command)
b.pack(side=tk.TOP) # re-pack button in vertical direction
return b
# override _Spacer() to create vertical separator
def _Spacer(self):
s = tk.Frame(self, width=26, relief=tk.RIDGE, bg="DarkGray", padx=2)
s.pack(side=tk.TOP, pady=5) # pack in vertical direction
return s
# disable showing mouse position in toolbar
def set_message(self, s):
pass
root = tk.Tk()
root.wm_title("Embedding in Tk")
fig = Figure(figsize=(5, 4), dpi=100)
t = np.arange(0, 3, .01)
fig.add_subplot().plot(t, 2 * np.sin(2 * np.pi * t))
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)
toolbar = VerticalNavigationToolbar2Tk(canvas, root)
toolbar.update()
toolbar.pack(side=tk.LEFT, fill=tk.Y)
root.mainloop()
And the output:

How to embed matplotlib graph in some area of a tkinter canvas?

Hello I am trying to embed a matplotlib graph to an especific area of a canvas, and I am having some problems trying to make the toolbar work properly. Here is what I have so far:
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import tkinter as tk
def on_closing():
root.quit()
root.destroy()
root = tk.Tk()
root.protocol("WM_DELETE_WINDOW", on_closing)
canvas = tk.Canvas(root, width = 500, height=400, highlightthickness=0)
canvas.pack()
# create Frame
x0, y0, x1, y1 = (10, 10, 490, 390)
frame = tk.Frame(canvas, width=x1-x0, height=y1-y0)
window = canvas.create_window(x0, y0, anchor="nw",
window=frame, width=x1-x0, height=y1-y0)
# Create matplotlib graph
figure, ax = plt.subplots()
ax.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
ax.set(xlabel='something', ylabel='something',
title='something')
ax.grid()
canvas_matplotlib = FigureCanvasTkAgg(figure, frame)
canvas_matplotlib.draw()
canvas_matplotlib.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
toolbar = NavigationToolbar2Tk(canvas_matplotlib, frame)
toolbar.update()
canvas_matplotlib._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
root.mainloop()
I dont understand why the toolbar wont appear.
EDIT:
What I want is for the plot and the toolbar to occupy exactly the area of the canvas defined.

How to resize matplotlib graph in tkinter window

I'm trying to set up some program that includes a matplotlib graph and tkinter buttons and whatnot below it. However, the matplotlib graph occupies the entire window overlaying the tkinter buttons and stuff.
I'd tried using pack, but it doesn't let me put stuff side by side, so I'd like the tkinter widgets to be arranged with .grid or coordinates.
from tkinter import *
from tkinter import StringVar
import tkinter
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
def eggs():
print("eggs")
root = Tk()
root.geometry("600x600")
root.title("eggs")
fig = Figure(figsize=(10, 6), dpi=100)
x = [1,2,3,4]
y = [1,2,3,4]
AS = [10/2**0]
fig.add_subplot(111).plot(x,y)
#fig.add_subplot(111).plot(AS)
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)
testbutton = Button(root, text = "test button", command = eggs)
testbutton.place(x=100, y=550)
root.mainloop()
Wanting the top part of the window to be occupied by the graph and the buttons and other additional stuff below it.
You can use one Frame to keep graph and its toolbar vertically, and another Frame to keep buttons horizontally. And then you can use pack() to put one Frame at top top and other at the bottom.
The only problem makes figsize=(10, 6) which needs more space than "600x600"
BTW: you can use Button(toolbar, ...) to add button to NavigationToolbar2Tk - see "my tool".
]1
import tkinter as tk
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
# --- functions ---
def eggs():
print("eggs")
# --- main ---
x = [1, 2, 3, 4]
y = [1, 2, 3, 4]
AS = [10/2**0]
# ---
root = tk.Tk()
root.geometry("600x600")
root.title("eggs")
# ---
frame_top = tk.Frame(root)
frame_top.pack(fill='both', expand=True)
fig = Figure(dpi=100) # figsize=(10, 6),
fig.add_subplot(111).plot(x,y)
#fig.add_subplot(111).plot(AS)
canvas = FigureCanvasTkAgg(fig, master=frame_top) # A tk.DrawingArea.
canvas.draw()
canvas.get_tk_widget().pack(fill='both', expand=True)
toolbar = NavigationToolbar2Tk(canvas, frame_top)
toolbar.update()
tool = tk.Button(toolbar, text="my tool")
tool.pack(side='left')#, fill='x', expand=True)
# ---
frame_bottom = tk.Frame(root)
frame_bottom.pack(fill='x')
button1 = tk.Button(frame_bottom, text="button1")
button1.pack(side='left', fill='x', expand=True)
button2 = tk.Button(frame_bottom, text="button2")
button2.pack(side='left', fill='x', expand=True)
button3 = tk.Button(frame_bottom, text="button3")
button3.pack(side='left', fill='x', expand=True)
# ---
root.mainloop()

Matplotlib figure.savefig() tkinter

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')

Black box around matplotlib graph in Tkinter

I'm embedding a pyplot graph in a Tkinter frame. There's a thick black line around the entire figure that I'd like to get rid of. It only appears when my Tkinter window is actively selected:
I'm using Python 2.7.6 on Mac OS 10.9. Here's my code:
from Tkinter import *
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
class PlotFrame(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.fig = plt.figure()
self.plot = self.fig.add_subplot(1, 1, 1)
self.canvas = FigureCanvasTkAgg(self.fig, master=self)
self.canvas.show()
self.canvas.get_tk_widget().grid(row=0, column=0, sticky=(N), padx=20, pady=20)
root = Tk()
plot_frame = PlotFrame(root)
plot_frame.grid(row=0, column=0)
root.mainloop()
Thanks!
That is controlled by the highlightthickness and highlightcolor attributes of the canvas widget. Set highlightthickness to zero if you don't want to see it.

Categories