2013-02-15 14 views
10

Qualcuno sa come ottenere gli eventi del pulsante 'casa', 'indietro' e 'avanti' da una cifra matplotlib?matplotlib aggancio agli eventi del tasto home/back/forward

Ho bisogno gli eventi di chiamare alcune delle mie funzioni in modo tale che le mie trame si comportano correttamente quando coloro pulsante viene premuto, cioè il comportamento di default non sta facendo quello che ho bisogno di fare

Matplotlib assume il set di dati di fondo è costante e che tutto ciò che serve è ripristinare i limiti dell'asse x/y e sostituirli per quei pulsanti - sfortunatamente questa ipotesi non è vera per il mio caso - Ho uno stack di dati che deve essere spinto e scoppiato quando questi eventi vengono attivati ​​

risposta

14

Matplotlib non prevede 'casa', 'Indietro' o 'in avanti' evento pulsante.

Per aggiungere un callback che verrà chiamato con l'evento del pulsante 'home', 'back' o 'forward', un approccio comune è quello di sottoclasse di un backend matplotlib.
Ma io non sono favorevole a questo approccio. Io penso che abbia due svantaggi:

  1. Se si desidera utilizzare diversi backend, è necessario sottoclasse ciascuno di essi.
  2. Distribuire il proprio backend al di fuori di matplotlib non è banale. Il tuo back-end deve essere un modulo che deve essere in PYTHONPATH.

Poiché nessuno dei backend forniti da matplotlib sovrascrive home, back e forward metodi NavigationToolbar2 s'.Preferisco l'approccio più conciso per le scimmie.
Ad esempio, è possibile sostituire lo homecon il proprio metodo.

import matplotlib.pyplot as plt 
from matplotlib.backend_bases import NavigationToolbar2 

home = NavigationToolbar2.home 

def new_home(self, *args, **kwargs): 
    print 'new home' 
    home(self, *args, **kwargs) 

NavigationToolbar2.home = new_home 

fig = plt.figure() 
plt.text(0.35, 0.5, 'Hello world!', dict(size=30)) 
plt.show() 

Possiamo stile anche di matplotlib mimica mpl_connect.

import matplotlib.pyplot as plt 
from matplotlib.backend_bases import NavigationToolbar2, Event 

home = NavigationToolbar2.home 

def new_home(self, *args, **kwargs): 
    s = 'home_event' 
    event = Event(s, self) 
    event.foo = 100 
    self.canvas.callbacks.process(s, event) 
    home(self, *args, **kwargs) 

NavigationToolbar2.home = new_home 

def handle_home(evt): 
    print 'new home' 
    print evt.foo 

fig = plt.figure() 
fig.canvas.mpl_connect('home_event', handle_home) 
plt.text(0.35, 0.5, 'Hello world!', dict(size=30)) 
plt.show() 
+0

mi rendo conto che accettare una risposta non costituisce l'assegnazione della taglia - leggermente non intuitiva; lieto di averlo notato con un'ora di anticipo, spero che nymk ce l'abbia fatta. molte grazie a tutte le risposte di alta qualità – bph

4

Se si riuscisse a chiamare semplicemente alcune funzioni ogni volta che l'asse x o y viene ridimensionato, l'attacco più semplice sarebbe quello di eseguire il binding a xlim_changed e ylim_changed eventi generati dai tuoi assi. Per esempio:

def on_xlim_change(*args): 
      print "do your pushing and popping here..." 
    ax = gca() 
    ax.callbacks.connect('xlim_changed',on_xlim_change) 

Questa richiamata eseguito ogni volta che si preme i tasti avanti, indietro o di casa, così come quando si utilizza la pentola o strumenti di zoom (almeno con i backend WX e GTK). Tuttavia, si esegue ancora dopo che matplotlib ha già eseguito il solito riscalaggio degli assi.

Se si desidera accedere direttamente a tali richiami di pulsanti direttamente, non riesco a vedere un modo semplice indipendente dal back-end poiché la gestione degli eventi funzionerà in modo diverso a seconda del back-end che si sta utilizzando. Penso che l'approccio di base sia la sottoclasse matplotlib.backends.backend_<name>.NavigationToolbar2<name> e l'override dei metodi forward, back e home. Dovrai comunque capire esattamente come incorporare la nuova classe della toolbar in base allo specifico backend che stai utilizzando.

Se si desidera implementare un controllo personalizzato "avanti/indietro" che non ha nulla a che fare con l'impostazione dei limiti degli assi, è preferibile utilizzare widgets.

5

Non sono a conoscenza di una soluzione indipendente dal back-end per questo problema. Ma quando si utilizza il Qt4Agg-backend, si può provare questo:

import matplotlib 
matplotlib.use("Qt4Agg") 
import pylab as p 

def home_callback(): 
    print "home called" 

def back_callback(): 
    print "back called" 

def forward_callback(): 
    print "forward called" 

p.ion() 
p.plot(p.random((10))) 

fm = p.get_current_fig_manager() 

fm.toolbar.actions()[0].triggered.connect(home_callback) 
fm.toolbar.actions()[1].triggered.connect(back_callback) 
fm.toolbar.actions()[2].triggered.connect(forward_callback) 

Per prima cosa ho ottenere il manager cifra attuale in modo da poter accedere alla sua barra degli strumenti. Quindi posso collegare ulteriori callback alle sue azioni.

Se si utilizza QT4Agg come back-end non è un'opzione per voi potremmo provare a fare qualcosa di simile per gli altri backend.

Problemi correlati