Как создать перетаскиваемую легенду в matplotlib? - PullRequest
40 голосов
/ 29 марта 2010

Я рисую легенду на объекте осей в matplotlib, но позиционирование по умолчанию, которое утверждает, что помещает его в умное место, похоже, не работает. В идеале, я бы хотел, чтобы легенда была перетаскиваемой пользователем. Как это можно сделать?

Ответы [ 3 ]

29 голосов
/ 30 марта 2010

Примечание: теперь оно встроено в matplotlib

leg = plt.legend()
if leg:
    leg.draggable()

будет работать как положено


Ну, я нашел кусочки решения, разбросанные по спискам рассылки. Я придумал хороший модульный кусок кода, который вы можете вставить и использовать ... вот он:

class DraggableLegend:
    def __init__(self, legend):
        self.legend = legend
        self.gotLegend = False
        legend.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)
        legend.figure.canvas.mpl_connect('pick_event', self.on_pick)
        legend.figure.canvas.mpl_connect('button_release_event', self.on_release)
        legend.set_picker(self.my_legend_picker)

    def on_motion(self, evt):
        if self.gotLegend:
            dx = evt.x - self.mouse_x
            dy = evt.y - self.mouse_y
            loc_in_canvas = self.legend_x + dx, self.legend_y + dy
            loc_in_norm_axes = self.legend.parent.transAxes.inverted().transform_point(loc_in_canvas)
            self.legend._loc = tuple(loc_in_norm_axes)
            self.legend.figure.canvas.draw()

    def my_legend_picker(self, legend, evt): 
        return self.legend.legendPatch.contains(evt)   

    def on_pick(self, evt): 
        if evt.artist == self.legend:
            bbox = self.legend.get_window_extent()
            self.mouse_x = evt.mouseevent.x
            self.mouse_y = evt.mouseevent.y
            self.legend_x = bbox.xmin
            self.legend_y = bbox.ymin 
            self.gotLegend = 1

    def on_release(self, event):
        if self.gotLegend:
            self.gotLegend = False

... и в вашем коде ...

def draw(self): 
    ax = self.figure.add_subplot(111)
    scatter = ax.scatter(np.random.randn(100), np.random.randn(100))


legend = DraggableLegend(ax.legend())

Я написал письмо группе пользователей Matplotlib, и Джон Хантер был любезен добавить свое решение в SVN HEAD.

В четверг, 28 января 2010 года, в 15:02, Адам. Фрейзер писал:

Я думал, что поделюсь решением проблемы перетаскиваемых легенд мне потребовалось навсегда, чтобы ассимилировать все рассеянные знания о списки рассылки ...

Круто - хороший пример. Я добавил код в legend.py. Теперь вы можете сделать

leg = ax.legend ()
leg.draggable ()

для включения режима перетаскивания. Вы можете неоднократно вызывать эту функцию для переключения перетаскиваемое состояние.

Надеюсь, это поможет людям, работающим с matplotlib.

14 голосов
/ 20 сентября 2011

В более новых версиях Matplotlib (v1.0.1) это встроено.

def draw(self): 
    ax = self.figure.add_subplot(111)
    scatter = ax.scatter(np.random.randn(100), np.random.randn(100))
    legend = ax.legend()
    legend.draggable(state=True)

Если вы используете matplotlib в интерактивном режиме (например, в режиме Pylab IPython).

plot(range(10), range(10), label="test label")
plot(range(10), [5 for x in range(10)], label="another test")
l = legend()
l.draggable(True)
3 голосов
/ 11 декабря 2018

В еще более новых версиях (3.0.2) оно устарело и потенциально будет представлять свойство в будущих версиях (следовательно, оно не будет вызываться).

plot(range(10), range(10), label="test label")
plot(range(10), [5 for x in range(10)], label="another test")
plt.legend().set_draggable(True)
...