Matplotlib/tkinter:在打开多个窗口时选择图例的事件
问题描述:
这是我的其他question关于tkinter中Matplotlib功能的跟进。我试图开发一个程序,当我训练模型时打开多个包含图的窗口。这些值作为字典存储在aveCR中,每个键存储多个数组。对于每个键,我将这些数组绘制在一个新窗口中,因此使用for循环打开一个新窗口(不知道这是否是好的做法!)Matplotlib/tkinter:在打开多个窗口时选择图例的事件
我遇到的问题是每个窗口的图例。打开/关闭行的功能只能在最后一个窗口中使用,我希望在打开的每个新窗口中都可以使用此功能。我知道self.lined
被for循环的最后一幅图覆盖,但我不确定是否应该将它添加到for循环。
我为aveCR添加了下面的虚拟数字,因此代码可以运行。任何意见在接近这个将不胜感激!
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
import tkinter as tk
class App:
def __init__(self,master):
self.master = master
# Frame for the training values
buttonFrame = tk.Frame(master)
buttonFrame.pack()
self.buttonGenerate = tk.Button(master=buttonFrame,
text='Train',
command=self.train)
self.buttonGenerate.grid(column=2,row=0)
def train(self):
aveCR = {0:{0:np.array([.582,1.081,1.507,1.872,2.180]),1:np.array([2.876,6.731,1.132,1.305,1.217])},
1:{0:np.array([.582,1.081,1.507,1.872,2.180]),1:np.array([2.876,6.731,1.132,1.305,1.217])}}
legend = {0: ['A', 'AB'], 1: ['A', 'AB']}
for i in range(len(aveCR)):
t = tk.Toplevel(self.master)
# Frame for the plot
plotFrame = tk.Frame(t)
plotFrame.pack()
f = plt.Figure()
self.ax = f.add_subplot(111)
self.canvas = FigureCanvasTkAgg(f,master=plotFrame)
self.canvas.show()
self.canvas.get_tk_widget().pack()
self.canvas.mpl_connect('pick_event', self.onpick)
# Plot
lines = [0] * len(aveCR[i])
for j in range(len(aveCR[i])):
X = range(0,len(aveCR[i][j]))
lines[j], = self.ax.plot(X,aveCR[i][j],label=legend[i][j])
leg = self.ax.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3,ncol=2, borderaxespad=0.)
self.lined = dict()
for legline, origline in zip(leg.get_lines(), lines):
legline.set_picker(5) # 5 pts tolerance
self.lined[legline] = origline
def onpick(self, event):
# on the pick event, find the orig line corresponding to the
# legend proxy line, and toggle the visibility
legline = event.artist
origline = self.lined[legline]
vis = not origline.get_visible()
origline.set_visible(vis)
# Change the alpha on the line in the legend so we can see what lines
# have been toggled
if vis:
legline.set_alpha(1.0)
else:
legline.set_alpha(0.2)
self.canvas.draw()
root = tk.Tk()
root.title("hem")
app = App(root)
root.mainloop()
答
这可能主要是一个设计问题。我会建议为每个绘图窗口使用一个类。然后,App
类可以根据需要实例化多个这些绘图窗口,并提供各自的数据作为参数。每个图表窗口管理图例和事件本身。
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
import Tkinter as tk
class Plotwindow():
def __init__(self, master, data, legend):
t = tk.Toplevel(master)
# Frame for the plot
plotFrame = tk.Frame(t)
plotFrame.pack()
f = plt.Figure()
self.ax = f.add_subplot(111)
self.canvas = FigureCanvasTkAgg(f,master=plotFrame)
self.canvas.show()
self.canvas.get_tk_widget().pack()
self.canvas.mpl_connect('pick_event', self.onpick)
# Plot
lines = [0] * len(data)
for j in range(len(data)):
X = range(0,len(data[j]))
lines[j], = self.ax.plot(X,data[j],label=legend[j])
leg = self.ax.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3,ncol=2, borderaxespad=0.)
self.lined = dict()
for legline, origline in zip(leg.get_lines(), lines):
legline.set_picker(5) # 5 pts tolerance
self.lined[legline] = origline
def onpick(self, event):
# on the pick event, find the orig line corresponding to the
# legend proxy line, and toggle the visibility
legline = event.artist
origline = self.lined[legline]
vis = not origline.get_visible()
origline.set_visible(vis)
# Change the alpha on the line in the legend so we can see what lines
# have been toggled
if vis:
legline.set_alpha(1.0)
else:
legline.set_alpha(0.2)
self.canvas.draw()
class App:
def __init__(self,master):
self.master = master
# Frame for the training values
buttonFrame = tk.Frame(master)
buttonFrame.pack()
self.buttonGenerate = tk.Button(master=buttonFrame,
text='Train',
command=self.train)
self.buttonGenerate.grid(column=2,row=0)
def train(self):
aveCR = {0:{0:np.array([.582,1.081,1.507,1.872,2.180]),1:np.array([2.876,6.731,1.132,1.305,1.217])},
1:{0:np.array([.582,1.081,1.507,1.872,2.180]),1:np.array([2.876,6.731,1.132,1.305,1.217])}}
legend = {0: ['A', 'AB'], 1: ['A', 'AB']}
self.windows = []
for i in range(len(aveCR)):
data = aveCR[i]
self.windows.append(Plotwindow(self.master,data, legend[i]))
root = tk.Tk()
root.title("hem")
app = App(root)
root.mainloop()
感谢您的帮助! –