I made a graph viewer GUI program in Python using Tkinter and matplotlib, where I switch between two graphs.
I have three problems I don't know how to fix:
- Can't change the radiobutton after I move the slider it stops updating.
- Can't change radiobutton after I switch the graph.
- I would like to switch between graphs with 1 subplot and 2 subplots, but when I switch to graph with 2 subplots with slider and radiobar I can't move back to first.
I think the problem might be in the way I update the slider and radiobutton
Here is the code:
import matplotlib
import tkinter as Tk
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
import numpy as np
from tkinter import *
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.backend_bases import key_press_handler
from matplotlib.widgets import Slider, RadioButtons
# Seperated out config of plot to just do it once
def config_plot():
fig, ax = plt.subplots()
ax.set(xlabel='time (s)', ylabel='voltage (mV)',
title='Graph One')
return (fig, ax)
class matplotlibSwitchGraphs:
def __init__(self, master):
self.master = master
self.frame = Frame(self.master)
self.fig, self.ax = config_plot()
self.graphIndex = 0
self.canvas = FigureCanvasTkAgg(self.fig, self.master)
self.config_window()
self.draw_graph_one()
self.frame.pack(expand=YES, fill=BOTH)
def config_window(self):
self.canvas.mpl_connect("key_press_event", self.on_key_press)
toolbar = NavigationToolbar2Tk(self.canvas, self.master)
toolbar.update()
self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
self.button = Button(self.master, text="Quit", command=self._quit)
self.button.pack(side=BOTTOM)
self.button_switch = Button(self.master, text="Switch Graphs", command=self.switch_graphs)
self.button_switch.pack(side=BOTTOM)
def plot_data(self):
def func3(x, y):
return (1 - x / 2 + x ** 5 + y ** 3) * np.exp(-(x ** 2 + y ** 2))
dx, dy = 0.05, 0.05
x = np.arange(-3.0, 3.0, dx)
y = np.arange(-3.0, 3.0, dy)
X, Y = np.meshgrid(x, y)
self.extent = np.min(x), np.max(x), np.min(y), np.max(y)
self.Z1 = np.add.outer(range(8), range(8)) % 2 # chessboard
self.Z2 = func3(X, Y)
def draw_graph_one(self):
self.plot_data()
self.ax.remove()
self.ax = plt.imshow(self.Z2, cmap=plt.cm.viridis, alpha=.9, interpolation='bilinear',
extent=self.extent)
self.canvas.draw()
def draw_graph_two(self):
self.plot_data()
self.ax.remove()
self.ax = plt.subplot(1, 2, 1)
self.ax = plt.imshow(self.Z1, cmap=plt.cm.gray, interpolation='nearest',
extent=self.extent)
self.ax = plt.subplot(1, 2, 2)
self.a = plt.imshow(self.Z2, cmap=plt.cm.viridis, alpha=.9, interpolation='bilinear',
extent=self.extent)
self.b = plt.imshow(self.Z1, cmap=plt.cm.gray, interpolation='nearest',
extent=self.extent)
self.canvas.draw()
plt.subplots_adjust(left=0.15, bottom=0.15)
slider_ax = plt.axes([0.06, 0.25, 0.0225, 0.5])
alfa_slider = Slider(slider_ax,
label="Transparency",
valmin=0,
valmax=1,
valinit=0,
orientation="vertical"
)
alfa_slider.on_changed(self.update_slider)
rax = plt.axes([0.06, 0.05, 0.15, 0.15])
radio = RadioButtons(rax, ('Reds', 'Greens', 'Blues', 'Oranges', 'Wistia', 'plasma', 'inferno'), active=0)
radio.on_clicked(self.update_radio)
self.canvas.draw()
def update_slider(self,alpha_):
self.b.set_alpha(alpha_)
self.canvas.draw()
def update_radio(self,label_):
self.b.set_cmap(label_)
self.canvas.draw()
def on_key_press(self,event,toolbar):
print("you pressed {}".format(event.key))
key_press_handler(event, self.canvas, toolbar)
def _quit(self):
self.master.quit() # stops mainloop
def switch_graphs(self):
# Need to call the correct draw, whether we're on graph one or two
self.graphIndex = (self.graphIndex + 1) % 2
if self.graphIndex == 0:
self.draw_graph_one()
else:
self.draw_graph_two()
def main():
root = Tk()
matplotlibSwitchGraphs(root)
root.mainloop()
if __name__ == '__main__':
main()
I tried to input update_slider and update_radio function inside of function, but than I cant use self.canvas.draw(). Also .remove() and .cla() doesn't clear the window.
Here is the view of the graphs I would like to switch between:
