Draggable matplotlib legend

I thought I'd share a solution to the draggable legend problem since
it took me forever to assimilate all the scattered knowledge on the
mailing lists...

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):
        legend = self.legend
        if evt.artist == 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

#...and in your code...

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

Cool -- nice example. I added the code to legend.py. Now you can do

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

to enable draggable mode. You can repeatedly call this func to toggle
the draggable state.

Thanks,
JDH

···

On Thu, Jan 28, 2010 at 3:02 PM, Adam Fraser <adam.n.fraser@...287...> wrote:

I thought I'd share a solution to the draggable legend problem since
it took me forever to assimilate all the scattered knowledge on the
mailing lists...

I thought I’d share a solution to the draggable legend problem since

it took me forever to assimilate all the scattered knowledge on the

mailing lists…

Cool – nice example. I added the code to legend.py. Now you can do

leg = ax.legend()

leg.draggable()

to enable draggable mode. You can repeatedly call this func to toggle

the draggable state.

Thanks,

JDH

Very useful addition for me. One question

In [8]: ax.leg
ax.legend ax.legend_

Has the second instance forgotten or left on purpose?

···

On Thu, Jan 28, 2010 at 3:48 PM, John Hunter <jdh2358@…83…287…> wrote:

On Thu, Jan 28, 2010 at 3:02 PM, Adam Fraser <adam.n.fraser@…287…> wrote:


The Planet: dedicated and managed hosting, cloud storage, colocation

Stay online with enterprise data centers and the best network in the business

Choose flexible plans and management services without long-term contracts

Personal 24x7 support from experience hosting pros just a phone call away.

http://p.sf.net/sfu/theplanet-com


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users


Gökhan

On Thu, Jan 28, 2010 at 3:48 PM, John Hunter <jdh2358@...287... Cool -- nice example. I added the code to legend.py. Now you can do

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

    to enable draggable mode. You can repeatedly call this func to toggle
    the draggable state.

Might I suggest that that be made:

leg.draggable(True)
leg.draggable(False)

or

leg.draggable('on')
leg.draggable('off')

or even a property:

leg.draggable = True

or some such. I'd be nice not to have to keep track of the current state.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer

NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Agreed. My favorite api for toggles is:

_state = True

def toggle(state=None):
    global _state
    old = _state
    if state is None:
        _state = not _state
    else:
        _state = state
    return old

···

On Thu, Jan 28, 2010 at 8:01 PM, Christopher Barker <Chris.Barker@...259...> wrote:

Might I suggest that that be made:

leg.draggable(True)
leg.draggable(False)

###

This lets you:

- toggle without arguments
- set state specifically as needed
- save previous state before setting it if you need to make temporary changes.

Cheers,

f

Good job!

+1

···

On Fri, Jan 29, 2010 at 4:14 AM, Fernando Perez <fperez.net@gmail.com> wrote:

On Thu, Jan 28, 2010 at 8:01 PM, Christopher Barker > > <Chris.Barker@…259…> wrote:

Might I suggest that that be made:

leg.draggable(True)

leg.draggable(False)

Agreed. My favorite api for toggles is:

_state = True

def toggle(state=None):

global _state

old = _state

if state is None:

    _state = not _state

else:

    _state = state

return old

This lets you:

  • toggle without arguments

  • set state specifically as needed

  • save previous state before setting it if you need to make temporary changes.

Cheers,

f


The Planet: dedicated and managed hosting, cloud storage, colocation

Stay online with enterprise data centers and the best network in the business

Choose flexible plans and management services without long-term contracts

Personal 24x7 support from experience hosting pros just a phone call away.

http://p.sf.net/sfu/theplanet-com


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users

OK, this is committed. Thanks for the suggestion.

JDH

···

On Thu, Jan 28, 2010 at 10:14 PM, Fernando Perez <fperez.net@...287...> wrote:

On Thu, Jan 28, 2010 at 8:01 PM, Christopher Barker > <Chris.Barker@...259...> wrote:

Might I suggest that that be made:

leg.draggable(True)
leg.draggable(False)

Agreed. My favorite api for toggles is:

_state = True

I did some refactoring and now the annotation is also draggable..
I also added an example,

examples/animation/draggable_legend.py

Regards,

-JJ

···

On Fri, Jan 29, 2010 at 10:28 AM, John Hunter <jdh2358@...287...> wrote:

On Thu, Jan 28, 2010 at 10:14 PM, Fernando Perez <fperez.net@...287...> wrote:

On Thu, Jan 28, 2010 at 8:01 PM, Christopher Barker >> <Chris.Barker@...259...> wrote:

Might I suggest that that be made:

leg.draggable(True)
leg.draggable(False)

Agreed. My favorite api for toggles is:

_state = True

OK, this is committed. Thanks for the suggestion.

JDH

------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation
Stay online with enterprise data centers and the best network in the business
Choose flexible plans and management services without long-term contracts
Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

added blitting support.

-JJ

···

On Fri, Jan 29, 2010 at 12:40 PM, Jae-Joon Lee <lee.j.joon@...287...> wrote:

I did some refactoring and now the annotation is also draggable..
I also added an example,

examples/animation/draggable_legend.py

Regards,

-JJ

On Fri, Jan 29, 2010 at 10:28 AM, John Hunter <jdh2358@...287...> wrote:

On Thu, Jan 28, 2010 at 10:14 PM, Fernando Perez <fperez.net@...287...> wrote:

On Thu, Jan 28, 2010 at 8:01 PM, Christopher Barker >>> <Chris.Barker@...259...> wrote:

Might I suggest that that be made:

leg.draggable(True)
leg.draggable(False)

Agreed. My favorite api for toggles is:

_state = True

OK, this is committed. Thanks for the suggestion.

JDH

------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation
Stay online with enterprise data centers and the best network in the business
Choose flexible plans and management services without long-term contracts
Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

One minor issue with the example is once you drag one of the items (legend or text or image) out of the plotting area there is no way to move them back unless you restart the example.

Do you get the same defect?

···

On Fri, Jan 29, 2010 at 11:40 AM, Jae-Joon Lee <lee.j.joon@…287…> wrote:

I did some refactoring and now the annotation is also draggable…

I also added an example,

examples/animation/draggable_legend.py

Regards,

-JJ

On Fri, Jan 29, 2010 at 10:28 AM, John Hunter <jdh2358@…287…> wrote:

On Thu, Jan 28, 2010 at 10:14 PM, Fernando Perez <fperez.net@gmail.com> wrote:

On Thu, Jan 28, 2010 at 8:01 PM, Christopher Barker > > >> <Chris.Barker@…2155…> wrote:

Might I suggest that that be made:

leg.draggable(True)

leg.draggable(False)

Agreed. My favorite api for toggles is:

_state = True

OK, this is committed. Thanks for the suggestion.

JDH


The Planet: dedicated and managed hosting, cloud storage, colocation

Stay online with enterprise data centers and the best network in the business

Choose flexible plans and management services without long-term contracts

Personal 24x7 support from experience hosting pros just a phone call away.

http://p.sf.net/sfu/theplanet-com


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users


The Planet: dedicated and managed hosting, cloud storage, colocation

Stay online with enterprise data centers and the best network in the business

Choose flexible plans and management services without long-term contracts

Personal 24x7 support from experience hosting pros just a phone call away.

http://p.sf.net/sfu/theplanet-com


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users


Gökhan