> 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-users