2017-10-19 5 views
0

Ceci est un suivi de mon autre question sur la fonctionnalité Matplotlib dans tkinter. J'essaie de développer un programme qui ouvre plusieurs fenêtres contenant des parcelles lorsque je forme un modèle. Les valeurs sont stockées dans aveCR en tant que dictionnaire avec chaque clé stockant plusieurs tableaux. Pour chaque clé, je trace les tableaux dans une nouvelle fenêtre et utilise donc une boucle for pour ouvrir une nouvelle fenêtre (je ne sais pas si c'est une bonne pratique!)Matplotlib/tkinter: Sélection d'événement sur la légende lors de l'ouverture de plusieurs fenêtres

Le problème que j'ai est avec la légende pour chaque fenêtre. La possibilité d'activer/désactiver les lignes n'est disponible que sur la dernière fenêtre et j'aimerais que cette fonctionnalité soit disponible à chaque nouvelle fenêtre ouverte. Je sais que self.lined est remplacé par le tracé final de la boucle for, mais je ne suis pas sûr si je devrais ajouter cela à la boucle for.

J'ai ajouté des figures factices ci-dessous pour aveCR, afin que le code puisse être exécuté. Tout conseil en approchant cela serait apprécié!

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

Répondre

0

Ceci est probablement principalement un problème de conception. Je recommanderais d'utiliser une classe pour chaque fenêtre de tracé. La classe App peut alors instancier autant de ces fenêtres de tracé que nécessaire, en fournissant les données respectives en tant qu'arguments. Chaque fenêtre de tracé gère la légende et les événements pour lui-même.

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() 
+0

Merci pour votre aide! –