> 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