> The event.x and event.y is the position of the mouse, and often this
> would not be the position of the legend (lower left corner) you want.
> I guess a common practice is to calculate how much your mouse moved
> since you started dragging and adjust the position of the legend from
> its original position by the same amount. What I would do is, in the
> on_pick call, save the current location of the mouse and the current
> location of the legend. And, when on_motion is called, calculate the
> dx, dy of your current mouse position from the saved (original) mouse
> position, and set the location of the legend by adding the same amount
> to the original legend position. Of course, the coordinate need to be
> converted in a proper system.

This is what I have attempted to do below.  Here is the relevant part:

    #pick the legend
    def on_pick(self, event):
        legend = self.legend
        if event.artist == legend:
            bbox = self.legend.get_window_extent()  #gets the box of the legend.
            self.mouse_x = event.mouseevent.x  #get mouse coordinates
at time of pick.
            self.mouse_y = event.mouseevent.y
            self.legend_x = bbox.xmin          #get legend coordinates
at time of pick.
            self.legend_y = bbox.ymin

            self.gotLegend = 1  #indicates we picked up the legend.

    #drag the legend
    def on_motion(self, event):
        if self.gotLegend == 1:
            mouse_diff_x = self.mouse_x - event.x  #how much the mouse moved.
            mouse_diff_y = self.mouse_y - event.y

            #move the legend from its previous location by that same amount
            self.legend._loc=(self.legend_x + mouse_diff_x,
self.legend_y + mouse_diff_y)
            self.canvas.draw()
            self.parent.Refresh()

Now when I run this, the legend just disappears (well, is moved to somewhere
off the screen).

For those with wx installed, runnable sample follows...

Thanks,
Che

#Boa:Frame:Frame1

import wx

import matplotlib
matplotlib.interactive(True)
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
from matplotlib.figure import Figure

def create(parent):
    return Frame1(parent)

[wxID_FRAME1, wxID_FRAME1NOTEBOOK1, wxID_FRAME1PANEL1,
] = [wx.NewId() for _init_ctrls in range(3)]

class PlotPanel(wx.Panel):
    def __init__(self, parent,id = -1, color = None,\
        dpi = None, style = wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):

        self.parent = parent
        self.line_collections_list = []

        wx.Panel.__init__(self, parent, **kwargs)

        self.figure = Figure(None, dpi)
        self.canvas = FigureCanvasWxAgg( self, -1, self.figure )

        #Connect all the mpl events
        self.canvas.mpl_connect('motion_notify_event', self.on_motion)
        self.canvas.mpl_connect('pick_event', self.on_pick)
        self.canvas.mpl_connect('button_release_event', self.on_release)

        self.gotLegend = 0  #to begin, legend is not picked.

        self._SetInitialSize()

        self.Bind(wx.EVT_SIZE, self._onSize)
        self.state = 'Initial'
        self.draw()

    def _onSize(self, event):
        self._SetSize()
        event.Skip()

    def _SetSize( self ):
        pixels = tuple( self.GetClientSize() )
        self.SetSize( pixels )
        self.canvas.SetSize( pixels )
        self.figure.set_size_inches( float( pixels[0] )/self.figure.get_dpi(),
                                     float( pixels[1] )/self.figure.get_dpi() )

    def _SetInitialSize(self,):
        pixels = self.parent.GetClientSize()
        self.canvas.SetSize(pixels)
        self.figure.set_size_inches( (pixels[0])/self.figure.get_dpi(),
         (pixels[1])/self.figure.get_dpi(), forward=True )


    def draw(self):
        self.subplot = self.figure.add_subplot(111)
        line, = self.subplot.plot([1,2,3],[4,5,6],'o',picker=5)
        self.line_collections_list.append(line)

        #Legend
        self.legend = self.subplot.legend(self.line_collections_list,
['1'], numpoints=1)
        self.legend.set_picker(self.my_legend_picker)

    #pick up the legend patch
    def my_legend_picker(self, legend, event):
        return self.legend.legendPatch.contains(event)

    #pick the legend
    def on_pick(self, event):
        legend = self.legend
        if event.artist == legend:
            bbox = self.legend.get_window_extent()  #gets the box of the legend.
            self.mouse_x = event.mouseevent.x  #get mouse coordinates
at time of pick.
            self.mouse_y = event.mouseevent.y
            self.legend_x = bbox.xmin          #get legend coordinates
at time of pick.
            self.legend_y = bbox.ymin

            self.gotLegend = 1  #indicates we picked up the legend.

    #drag the legend
    def on_motion(self, event):
        if self.gotLegend == 1:
            mouse_diff_x = self.mouse_x - event.x  #how much the mouse moved.
            mouse_diff_y = self.mouse_y - event.y

            #move the legend from its previous location by that same amount
            self.legend._loc=(self.legend_x + mouse_diff_x,
self.legend_y + mouse_diff_y)
            self.canvas.draw()
            self.parent.Refresh()

    #release the legend
    def on_release(self, event):
        if self.gotLegend == 1:
            self.gotLegend = 0
            print 'release'

class Frame1(wx.Frame):
    def _init_coll_boxSizer1_Items(self, parent):
        # generated method, don't edit

        parent.AddWindow(self.notebook1, 1, border=0, flag=wx.EXPAND)

    def _init_sizers(self):
        # generated method, don't edit
        self.boxSizer1 = wx.BoxSizer(orient=wx.VERTICAL)

        self._init_coll_boxSizer1_Items(self.boxSizer1)

        self.panel1.SetSizer(self.boxSizer1)

    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Frame.__init__(self, id=wxID_FRAME1, name='', parent=prnt,
              pos=wx.Point(333, 202), size=wx.Size(592, 474),
              style=wx.DEFAULT_FRAME_STYLE,
              title='moving the legend accurately')
        self.SetClientSize(wx.Size(584, 440))

        self.panel1 = wx.Panel(id=wxID_FRAME1PANEL1, name='panel1', parent=self,
              pos=wx.Point(0, 0), size=wx.Size(584, 440),
              style=wx.TAB_TRAVERSAL)

        self.notebook1 = wx.Notebook(id=wxID_FRAME1NOTEBOOK1, name='notebook1',
              parent=self.panel1, pos=wx.Point(0, 0), size=wx.Size(584, 440),
              style=0)


        self._init_sizers()

    def __init__(self, parent):
        self._init_ctrls(parent)
        graph = PlotPanel(self.notebook1)
        self.notebook1.AddPage(graph,'graph')

if __name__ == '__main__':
    app = wx.PySimpleApp()
    frame = create(None)
    frame.Show()

    app.MainLoop()

------------------------------------------------------------------------------
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Reply via email to