Skip to content

RectangleSelector does not work if start and end points are identical #10075

Closed

Description

@Rolf-Hempel

Bug report

If in a RectangleSelector the mouse does not move between button press and button release, wrong values for start and end coordinates are returned. It seems to me that those coordinates correspond to the last callback where the mouse had been moved between press and release.

The following example code in the Matplotlib documentation illustrates the consequences:

from pylab import *

def onselect(eclick, erelease):
  'eclick and erelease are matplotlib events at press and release'
  print(' startposition : (%f, %f)' % (eclick.xdata, eclick.ydata))
  print(' endposition   : (%f, %f)' % (erelease.xdata, erelease.ydata))
  print(' used button   : ', eclick.button)

def toggle_selector(event):
    print(' Key pressed.')
    if event.key in ['Q', 'q'] and toggle_selector.RS.active:
        print(' RectangleSelector deactivated.')
        toggle_selector.RS.set_active(False)
    if event.key in ['A', 'a'] and not toggle_selector.RS.active:
        print(' RectangleSelector activated.')
        toggle_selector.RS.set_active(True)

x = arange(100)/(99.0)
y = sin(x)
fig = figure
ax = subplot(111)
ax.plot(x,y)

toggle_selector.RS = RectangleSelector(ax, onselect, drawtype='line')
connect('key_press_event', toggle_selector)
show()

**If you start with drawing a line, everything works fine. If you then move the mouse to a different point, click it and release it without moving, the previous line shows up again (and the old coordinates are printed to stdout). If you draw a line from upper left to lower right, the detached line makes weird movements.

The example program works correctly with Matplotlib version 1.4.2.

Matplotlib version

  • Operating system: Windows 7 Professional 64bit
  • Matplotlib version: 2.1.1
  • Matplotlib backend (print(matplotlib.get_backend())): qt5agg
  • Python version: 3.6.3
  • Jupyter version (if applicable): -
  • Other libraries: -

I installed matplotlib with miniconda from the default channel.

Activity

  1. added this to the milestone on Dec 22, 2017
  2. tacaswell commented on Dec 22, 2017

    @tacaswell
    Member

    I suspect that we missed half of the de-bounce logic (skip updating the state but do not skip running the callback).

  3. Rolf-Hempel commented on Dec 22, 2017

    @Rolf-Hempel
    Author

    If I understand you correctly, you want to avoid running the callback if the mouse positition is identical at press and release time. That would change the behaviour as compared to version 1.4.2., though. There, when a "point" is selected instead of a rectangle, the callback is run with identical startpoint and endpoint coordinates. I use that in my code to differentiate between a real rectangle and a point. Actually, I found that useful in that I could invalidate a selected rectangle by just pressing and releasing the mouse without moving it in between.

  4. lkjell commented on Dec 26, 2017

    @lkjell
    Contributor

    The docs need an update on this one too. If you have a rectangle ABCD then the line will draw from vertex A to C regardless where start and stop positions are.

    Anyway, this is the same problem with SpanSelector that I tried to highlight in #9660. Do you want the span to reset when there are no movement etc.

    Callbacks should be called regardsless of state change. It should be the user that implements the guard if necessary. For example:

    from pylab import *
    from matplotlib.widgets import RectangleSelector
    
    class Onselect:
        state = None, None
    
        def __call__(self, eclick, erelease):
            if self.state[0] == eclick.xdata and self.state[1] == eclick.ydata:
                return
            else:
                self.state = eclick.xdata, eclick.ydata
    
            'eclick and erelease are matplotlib events at press and release'
            print(' startposition : (%f, %f)' % (eclick.xdata, eclick.ydata))
            print(' endposition   : (%f, %f)' % (erelease.xdata, erelease.ydata))
            print(' used button   : ', eclick.button)
    
    def toggle_selector(event):
        print(' Key pressed.')
        if event.key in ['Q', 'q'] and toggle_selector.RS.active:
            print(' RectangleSelector deactivated.')
            toggle_selector.RS.set_active(False)
        if event.key in ['A', 'a'] and not toggle_selector.RS.active:
            print(' RectangleSelector activated.')
            toggle_selector.RS.set_active(True)
    
    x = arange(100)/(99.0)
    y = sin(x)
    fig = figure
    ax = subplot(111)
    ax.plot(x,y)
    
    onselect = Onselect()
    
    toggle_selector.RS = RectangleSelector(ax, onselect, drawtype='line', interactive=True)
    connect('key_press_event', toggle_selector)
    show()
    
  5. modified the milestones: , on Mar 22, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions