From: John H. <jd...@gm...> - 2008-11-26 15:01:18
|
On Wed, Nov 26, 2008 at 5:34 AM, Egor Zindy <ez...@gm...> wrote: > Dear matplotlib devels, > > I wrote a selection widget someone else might find useful. The widget is > based on the slider widget.> > Things I implemented: > * blitting (bar still flashes once when clicked on, sorry about that!) > * Horizontal or vertical direction > * Multiple selection bars on a figure > * interaction between two bars to set a range I think this is a useful tool, but I would like to see a few enhancements, some of which you mention below. > Things I struggled with: > * When a bar is dragged towards one of the figure edges too quickly, it gets > stuck in its last recorded position on the graph (that should be the figure > edge). I think the cause of this is when your mouse leaves the axes, the axes stops processing events, so it no longer gets updates to move the bar. I'm not sure what the right solution is though. > * Don't know how to change the mouse pointer when on top of the bar (the <-> > pointer for a vertical bar would be nice) In backend bases there is a cursors enum::: In [5]: import matplotlib.backend_bases as bb In [7]: bb.cursors.HAND Out[7]: 0 In [8]: bb.cursors.MOVE Out[8]: 3 and you can use the canvas toolbar to change the cursor In [11]: fig.canvas.toolbar.set_cursor(bb.cursors.MOVE) > * Don't know how to define a range in pixels around the bar (for grabbing), > so used 0.01 of the full range instead Read the event handling and picking tutorial at http://matplotlib.sourceforge.net/users/event_handling.html if you haven't already. I suggest doing the hit testing in figure rather than data coordinates. So instead of val = event.xdata if val < self.val + self.radius ... do something like the following:: def _update(self, event) # store the line location in pixel space self.linex = event.x def _press(event): if abs(event.x-self.linex)<=5: # 5 pixels # hit! > * Haven't implemented dragging when a bar reaches the other bar (set with > set_barmin or set_barmax) but hasn't reached the limit of its range. > > How to test: > have mplbar.py and test_bar.py in the same directory, launch test_bar.py > > > Hope this all makes sense (somehow I doubt it). And like I said, if you guys > like it or want to adapt it further, please do, the code this is based on is > yours after all! With some additional cleanup along the lines of the above, I would be happy to accept this. Please document every method (I realize some exisint code does not meet this standard but we are trying to improve). Also, please use the rest conventions when documenting new code; the widgets code has not been ported over but a lot has -- see http://matplotlib.sourceforge.net/devel/documenting_mpl.html One feature you may want to consider. I think it would be nice to have color coded ticks, or possibly a static hspan along the regions where the bar can slide. Eg, see the following minor modification to test_bar:: bar1 = mplbar.Bar(ax1,valrange=[10,60],useblit=True, lw=2, color='g') ax1.axvspan(10, 60, ymin=0, ymax=0.05, facecolor='g', alpha=0.2) #range 10 to 60, init value set to 60, use blit, blue bar2 = mplbar.Bar(ax1,valrange=[10,60],valinit=60,useblit=True, lw=2, color='b') ax1.axvspan(10, 60, ymin=0.95, ymax=1.0, facecolor='blue', alpha=0.2) #range 30 to +inf (None = no bound), default set to 30, use blit, horizontal line, red bar3 = mplbar.Bar(ax1,valrange=[30,None],useblit=True, direction='horizontal', lw=2, color='r') ax1.axhspan(30, 2*npts, xmin=0.95, xmax=1.0, facecolor='red', alpha=0.2) Of course the use can always add this, so I am not sure if it is worth building in... but support for something like this via a kwar might be nice, eg Bar(blah, ..., showrange=True, rangespan=[0.95, 1.0]) JDH |