matplotlib fixed size when dragging RectangleSelector

Question:

When I click the center of RectangleSelector and drag it to the edges of axes, the width or height will be changed (become smaller). This behavior is different from EllipseSelector whose width and height don’t be changed and can be dragged outside current axes view. So how can keep RectangleSelector size when dragging?

enter image description here

Asked By: sfzhang

||

Answers:

I don’t know if there is an easier way to fix this behavior, but you could create a custom RectangleSelector overriding the _onmove method to make sure the rectangle X position (respectively Y position) is updated only when the width (respectively the height) do not change.

class CustomRectangleSelector(RectangleSelector):
    
    def _onmove(self, event):
        # Start bbox
        s_x0, s_x1, s_y0, s_y1 = self.extents
        start_width = np.float16(s_x1 - s_x0)
        start_height = np.float16(s_y1 - s_y0)
        
        super()._onmove(event)
        
        # Custom behavior only if selector is moving
        if not self._active_handle == 'C':  
            return
        
        # End bbox
        e_x0, e_x1, e_y0, e_y1 = self.extents
        end_width = np.float16(e_x1 - e_x0)
        end_height = np.float16(e_y1 - e_y0)

        if start_width != end_width:
            e_x0, e_x1 = s_x0, s_x1
            
        if start_height != end_height:
            e_y0, e_y1 = s_y0, s_y1
            
        self.extents = e_x0, e_x1, e_y0, e_y1

enter image description here

Answered By: thmslmr

Thanks to @thmslmr. I finally achieved the goal by override _draw_shape.

class CustomRectangleSelector(RectangleSelector):

def _draw_shape(self, extents):
    x0, x1, y0, y1 = extents
    xmin, xmax = sorted([x0, x1])
    ymin, ymax = sorted([y0, y1])
    
    # DO NOT apply the xy limits
    #xlim = sorted(self.ax.get_xlim())
    #ylim = sorted(self.ax.get_ylim())

    #xmin = max(xlim[0], xmin)
    #ymin = max(ylim[0], ymin)
    #xmax = min(xmax, xlim[1])
    #ymax = min(ymax, ylim[1])

    self._selection_artist.set_x(xmin)
    self._selection_artist.set_y(ymin)
    self._selection_artist.set_width(xmax - xmin)
    self._selection_artist.set_height(ymax - ymin)
    self._selection_artist.set_angle(self.rotation)
Answered By: sfzhang
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.