MEP9: Gestore dell'interazione globale #

Aggiungi un gestore globale per tutta l'interattività dell'utente con gli artisti; rendere qualsiasi artista ridimensionabile, spostabile, evidenziabile e selezionabile come desiderato dall'utente.

Stato n.

Discussione

Filiali e Pull request #

https://github.com/dhyams/matplotlib/tree/MEP9

Estratto n.

L'obiettivo è essere in grado di interagire con gli artisti matplotlib in un modo molto simile a come fanno i programmi di disegno. Quando appropriato, l'utente dovrebbe essere in grado di spostare, ridimensionare o selezionare un artista che è già sulla tela. Ovviamente, lo sceneggiatore ha in ultima analisi il controllo sulla possibilità di interagire con un artista o se è statico.

Questo codice per fare ciò è già stato implementato e testato privatamente e dovrebbe essere migrato dalla sua attuale implementazione "mixin" a una parte in buona fede di matplotlib.

Il risultato finale sarebbe avere quattro nuove parole chiave disponibili per matplotlib.artist.Artist: _moveable_, _resizeable_, _selectable_ e _highlightable_. L'impostazione di una qualsiasi di queste parole chiave su True attiverebbe l'interattività per quell'artista.

In effetti, questo MEP è un'estensione logica della gestione degli eventi in matplotlib; matplotlib supporta già interazioni di "basso livello" come la pressione del tasto sinistro del mouse, la pressione di un tasto o simili. Il MEP estende il supporto al livello logico, in cui vengono eseguiti richiami sugli artisti quando vengono rilevati determinati gesti interattivi da parte dell'utente.

Descrizione dettagliata #

Questa nuova funzionalità verrebbe utilizzata per consentire all'utente finale di interagire meglio con il grafico. Molte volte, un grafico è quasi ciò che l'utente desidera, ma è necessario un piccolo riposizionamento e/o ridimensionamento dei componenti. Piuttosto che costringere l'utente a tornare allo script per provare ed eseguire errori nella posizione, sarebbe appropriato un semplice trascinamento della selezione.

Inoltre, questo supporterebbe meglio le applicazioni che usano matplotlib; qui, l'utente finale non ha un accesso ragionevole o il desiderio di modificare la fonte sottostante per mettere a punto una trama. Qui, se matplotlib offrisse la capacità, si potrebbero spostare o ridimensionare gli artisti sulla tela per soddisfare le loro esigenze. Inoltre, l'utente dovrebbe essere in grado di evidenziare (con il mouse sopra) un artista e selezionarlo con un doppio clic, se l'applicazione supporta questo genere di cose. In questo MEP, vogliamo anche supportare l'evidenziazione e la selezione in modo nativo; spetta all'applicazione gestire ciò che accade quando l'artista viene selezionato. Una gestione tipica sarebbe quella di visualizzare una finestra di dialogo per modificare le proprietà dell'artista.

In futuro, inoltre (questo non fa parte di questo MEP), matplotlib potrebbe offrire finestre di dialogo di proprietà specifiche del backend per ciascun artista, che vengono generate in base alla selezione dell'artista. Questo eurodeputato sarebbe un trampolino di lancio necessario per questo tipo di capacità.

Al momento ci sono alcune funzionalità interattive in matplotlib (ad esempio legend.draggable()), ma tendono a essere sparse e non sono disponibili per tutti gli artisti. Questo eurodeputato cerca di unificare l'interfaccia interattiva e farla funzionare per tutti gli artisti.

L'attuale MEP include anche maniglie per il ridimensionamento degli artisti e caselle appropriate disegnate quando gli artisti vengono spostati o ridimensionati.

Implementazione n.

  • Aggiungere metodi appropriati all'"albero" degli artisti in modo che il gestore dell'interattività disponga di un'interfaccia coerente da gestire. I metodi proposti per aggiungere agli artisti, se devono supportare l'interattività, sono:

    • get_pixel_position_ll(self): ottiene la posizione in pixel dell'angolo in basso a sinistra del riquadro di delimitazione dell'artista

    • get_pixel_size(self): ottiene la dimensione del riquadro di delimitazione dell'artista, in pixel

    • set_pixel_position_and_size(self,x,y,dx,dy): imposta la nuova dimensione dell'artista, in modo tale che rientri nel riquadro di delimitazione specificato.

  • aggiungere funzionalità ai backend per 1) fornire cursori, poiché questi sono necessari per l'indicazione visiva di spostamento/ridimensionamento e 2) fornire una funzione che ottiene la posizione corrente del mouse

  • Implementare il manager. Questo è già stato fatto privatamente (dai dhyam) come mixin, ed è stato testato parecchio. L'obiettivo sarebbe quello di spostare la funzionalità del gestore negli artisti in modo che sia correttamente in matplotlib, e non come una "toppa di scimmia" come attualmente l'ho codificata.

Riepilogo attuale del mixin #

(Nota che questo mixin è per ora solo codice privato, ma ovviamente può essere aggiunto a un ramo)

InteractiveArtistMixin:

Classe Mixin per rendere mobile e possibilmente ridimensionabile qualsiasi oggetto generico disegnato su un canvas matplotlib. Il modello Powerpoint è seguito il più fedelmente possibile; non perché sono innamorato di Powerpoint, ma perché è quello che la maggior parte delle persone capisce. Un artista può anche essere selezionabile, il che significa che l'artista riceverà la richiamata on_activated() quando si fa doppio clic. Infine, un artista può essere evidenziabile, il che significa che viene disegnato un evidenziatore sull'artista ogni volta che il mouse ci passa sopra. In genere, anche gli artisti evidenziabili saranno selezionabili, ma questo è lasciato all'utente. Quindi, fondamentalmente ci sono quattro attributi che possono essere impostati dall'utente in base all'artista:

  • evidenziabile

  • selezionabile

  • mobile

  • ridimensionabile

Per essere spostabile (trascinabile) o ridimensionabile, l'oggetto che è il target del mixin deve supportare i seguenti protocolli:

  • get_pixel_position_ll(self)

  • get_pixel_size(self)

  • set_pixel_position_and_size(self,x,y,sx,sy)

Si noti che gli oggetti non ridimensionabili sono liberi di ignorare i parametri sx e sy. Per essere evidenziabile, l'oggetto che è il target del mixin deve supportare anche il seguente protocollo:

  • get_highlight(self)

Che restituisce un elenco di artisti che verranno utilizzati per disegnare il momento clou.

Se l'oggetto che è l'obiettivo del mixin non è un artista matplotlib, devono essere implementati anche i seguenti protocolli. Farlo di solito è abbastanza banale, poiché deve esserci un artista da qualche parte che viene disegnato. In genere il tuo oggetto instraderebbe semplicemente queste chiamate a quell'artista.

  • get_figure(self)

  • ottieni_assi(self)

  • contiene(sé,evento)

  • set_animated(self,flag)

  • draw(self,renderer)

  • get_visible(self)

Le seguenti notifiche vengono richiamate sull'artista e l'artista può facoltativamente implementarle.

  • on_select_begin(self)

  • on_select_end(auto)

  • on_drag_begin(self)

  • on_drag_end(self)

  • on_activated(self)

  • on_highlight(self)

  • on_right_click(self,evento)

  • on_left_click(self,evento)

  • on_middle_click(self,evento)

  • on_context_click(self,evento)

  • on_key_up(self,evento)

  • on_key_down(self,evento)

Le seguenti notifiche vengono richiamate nell'area di disegno, se nessun artista interattivo gestisce l'evento:

  • on_press(self,evento)

  • on_left_click(self,evento)

  • on_middle_click(self,evento)

  • on_right_click(self,evento)

  • on_context_click(self,evento)

  • on_key_up(self,evento)

  • on_key_down(self,evento)

Le seguenti funzioni, se presenti, possono essere utilizzate per modificare il comportamento dell'oggetto interattivo:

  • press_filter(self,event) # determina se l'oggetto vuole ricevere l'evento press indirizzato ad esso

  • handle_unpicked_cursor() # può essere utilizzato dall'oggetto per impostare un cursore mentre il cursore passa sopra l'oggetto quando viene deselezionato.

Supporta più tele, mantenendo un blocco di trascinamento, un notificatore di movimento e un flag "abilitato" globale per tela. Supporta il ridimensionamento delle proporzioni fisse tenendo premuto il tasto Maiusc durante il ridimensionamento.

Problemi noti:

  • Zorder non viene rispettato durante le operazioni di selezione/trascinamento. A causa della tecnica blit utilizzata, non credo che questo possa essere risolto. L'unico modo che mi viene in mente è cercare tutti gli artisti che hanno uno zorder maggiore di me, impostarli tutti su animati e quindi ridisegnarli tutti sopra durante ogni aggiornamento del trascinamento. Questo potrebbe essere molto lento; bisogno di provare.

  • il mixin funziona solo per i backend wx a causa di due cose: 1) i cursori sono hardcoded, e 2) c'è una chiamata a wx.GetMousePosition() Entrambe queste carenze sono ragionevolmente risolte facendo in modo che ciascun backend fornisca queste cose.

Compatibilità con le versioni precedenti #

Nessun problema con la compatibilità con le versioni precedenti, anche se una volta che questo è a posto, sarebbe opportuno rendere obsolete alcune delle funzioni interattive esistenti (come legend.draggable())

Alternative #

Nessuno che io sappia.