2012-07-18 16 views

Respuesta

25

Sí, es posible gracias al marco de manejo de eventos de matplotlib. No pude encontrar un ejemplo ya escrito que haga lo que le interesa particularmente, así que escribí uno (que presentaré para su inclusión en la fuente matplotlib).

Leería http://matplotlib.sourceforge.net/users/event_handling.html a fondo para comprender mejor lo que está sucediendo. Tenga en cuenta que, aunque suena como la solución perfecta "pick_event" es para clics del mouse, no para eventos del mouse y no funciona en este caso.

Mi código, lo que podría ser objetivado muy bien si uno quiere, se ve así:

import matplotlib.pyplot as plt 

fig = plt.figure() 
ax = plt.axes() 


points_with_annotation = [] 
for i in range(10): 
    point, = plt.plot(i, i, 'o', markersize=10) 

    annotation = ax.annotate("Mouseover point %s" % i, 
     xy=(i, i), xycoords='data', 
     xytext=(i + 1, i), textcoords='data', 
     horizontalalignment="left", 
     arrowprops=dict(arrowstyle="simple", 
         connectionstyle="arc3,rad=-0.2"), 
     bbox=dict(boxstyle="round", facecolor="w", 
        edgecolor="0.5", alpha=0.9) 
     ) 
    # by default, disable the annotation visibility 
    annotation.set_visible(False) 

    points_with_annotation.append([point, annotation]) 


def on_move(event): 
    visibility_changed = False 
    for point, annotation in points_with_annotation: 
     should_be_visible = (point.contains(event)[0] == True) 

     if should_be_visible != annotation.get_visible(): 
      visibility_changed = True 
      annotation.set_visible(should_be_visible) 

    if visibility_changed:   
     plt.draw() 

on_move_id = fig.canvas.mpl_connect('motion_notify_event', on_move) 

plt.show() 

Esperemos que todo debería ser bastante fácil de leer. Una visión general de alto nivel del código va:

  • Crear una lista de [Punto, anotación] pares, en los que de manera predeterminada la anotación no es visible
  • registrar una función, "on_move", que se llamará cada vez hay movimiento del mouse detectado
  • La función on_move recorre cada punto y la anotación; si el mouse ahora está sobre uno de los puntos, haz visible su anotación asociada, si no lo es, hazla invisible. (Contiene el método es documented here)

Screenshot of the result

+0

Ah preciosa, gracias a que @pelson para el código y explicación. Por lo tanto, esto significa que no hay un controlador de eventos directo para situarse sobre una ubicación en el gráfico. Debe hacerse de forma indirecta. –

+0

No. Puede acceder a las coordenadas xey del evento mouse en la función 'on_move'. De eso puedes hacer cualquier cosa. En mi caso, miré a través de todos los artistas e identifiqué si alguno contenía la posición del mouse, pero también podías actualizar la posición de una sola instancia de anotación dada la xey. – pelson

+0

Sí, tiene razón en ese punto, pero estaba buscando algo así como registrar una devolución de llamada a un artista en particular con un evento como "hover_event" Eso es lo que quiero decir con un evento directo –