Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

lucasgruwez
Copy link

PR summary

Tangent to #30541
Allows for zooming in a single axis using the zoom rectangle by dragging only in one direction.

Screen.Recording.2025-09-14.at.01.37.29.mov

PR checklist

@rcomer
Copy link
Member

rcomer commented Sep 13, 2025

I note that the existing x-/y- modifiers do not really work when using my laptop's touchpad1, but this proposal does work nicely 👍

Footnotes

  1. If I hold x and the left button, nothing happens when I drag. I can get it to work by making the box and then pressing x before I let go, but I don't get the visual of the box turning into two parallel lines. If I use an external mouse, everything works as it should so it definitely seems to be an issue with the touchpad.

@timhoffm
Copy link
Member

This is an interesting concept, though I was a bit surprised at first. Is there any precedence that other programs use this approach?

Also, would it be a good idea to give some sort of visual aide, with the goals (i) to make it clear that something special is going on and (ii) give an indication of the area the mouse has to be in so that the special handling applies? e.g. something like marking the region:
grafik

@lucasgruwez
Copy link
Author

Matlab has similar behavior. Could implement something similar where the lines at the edge indicate the region the mouse needs to be in?

Screen.Recording.2025-09-14.at.19.18.48.mov

@timhoffm
Copy link
Member

timhoffm commented Sep 14, 2025

The range marker is a good visualization to indicate the difference. Though, I would like to additionally keep dashed lines as an extension of the whiskers, because that helps to ensure relevant data points are included.

That said, all the visual changes would need refactoring and backend-dependent implementation as currently all visualization is done via RubberBandBase and that does only cover the rectangle without the ability for further modification.

class RubberbandBase(ToolBase):

@lucasgruwez
Copy link
Author

Example of whiskers and dashed rectangle using QtCairo and QtAgg backends. The width of the whiskers represents the region the mouse needs to be in for single-axis zoom.

Excuse the lack of mouse pointer in the screenshot.

Screenshot 2025-09-14 at 23 10 09

@lucasgruwez
Copy link
Author

lucasgruwez commented Sep 14, 2025

Backends so far

  • tk
  • gtk (unable to test on my machine, but code is written)
  • Qt
  • wx
  • WebAgg
  • MacOS

@lucasgruwez
Copy link
Author

All backends have been updated. As previously mentioned, I was unable to test gtk on my machine, but I have tested all other backends. Several other fixes were also included:

  • Ensure that the zoom rubber band is dashed in all backends (it was not in WebAgg).
  • Fix the Tk rubber band: the implicit black line colour was not working, so it was set explicitly instead.

@timhoffm
Copy link
Member

All backends have been updated. As previously mentioned, I was unable to test gtk on my machine, but I have tested all other backends. Several other fixes were also included:

  • Ensure that the zoom rubber band is dashed in all backends (it was not in WebAgg).
  • Fix the Tk rubber band: the implicit black line colour was not working, so it was set explicitly instead.

Could you move them out into a separate PR? It makes reviewing this PR simpler if we don't have multiple topics.

This PR is a good prove-of-concept and from a first glance feature complete - thanks for implementing all the backends!

We still need to think about the architecture and how to bring it into the main library. As is, the draw_whisker method is an API change that will break third-party backends. We'll have to decide

  • API design: whether that method is the right approach (other alternatives could be integrate it into the rubberband, or start a more general approach for drawing some primitives in the backend in the anticipation that we will have more interactivity (e.g. PoC: GUI-native crosshair cursor #30516).
  • API compatibility: As is this is breaking 3rd party backends, which is a no-go. We could either work around this through special-casing (test if the method is available in the backend) or go for a more structured approach of API versioning [ENH]: Backend versioning #30559.

@lucasgruwez
Copy link
Author

The bugfixes have been separated into #30560

Regarding third-party backends, I don't fully understand how these would break. The empty draw_whiskers method in the base class NavigationToolbar2 appears to address this concern. During development, even before integrating the whiskers into a new backend, the backend would continue to function, albeit without displaying the whiskers.

lib/matplotlib/backend_bases.py:2938

Attempting to use the ipympl backend in Jupyter leads to the following behaviour:
no whiskers are displayed, only a zoom box. There appear to be console messages indicating that there is no handler for the whiskers event, as it is a subclass of the WebAgg backend, which calls this event.

Screenshot 2025-09-15 at 18 05 51

@lucasgruwez
Copy link
Author

Tested with mplcairo third party backend and got the following results

  • mplcairo.macosx: Whiskers inherited from mpl macosx class
  • mplcairo.qt: No whiskers drawn, box only. No errors thrown
  • mplcairo.wx: Scaling is off on my machine, whiskers still work though
  • mplcairo.tk: Whiskers inherited from mpl tk class
  • mplcairo.gtk: Whiskers inherited from mpl gtk class

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants