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

Skip to content

Change cursor when hovering over draggable artists #25412

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

daniilS
Copy link
Contributor

@daniilS daniilS commented Mar 8, 2023

PR Summary

Currently, there's no visual indication that an artist is draggable. This sets the cursor to Cursors.MOVE when the mouse is hovering over a DraggableBase instance which can be picked.

A possible addition would be to set the widget lock in on_pick() until on_release(), which would prevent other draggables/widgets/toolbar modes from being active at the same time, but I wasn't sure if there is a reason that widgetlock isn't already being used.

draggable.legend.webm

Copy link
Contributor

@greglucas greglucas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is nice to know that you can interact with the component 👍

@greglucas
Copy link
Contributor

I was using the code from #25428 (comment) to test this.

import matplotlib.pyplot as plt
plt.plot(range(5), label='bob')
leg = plt.legend()
leg.set_draggable(True, update='bbox')
plt.show()

@QuLogic
Copy link
Member

QuLogic commented Mar 14, 2023

Maybe this should get a .. versionmodified:: annotation in set_draggable?

@daniilS
Copy link
Contributor Author

daniilS commented Mar 22, 2023

@greglucas , I had a look at the macosx issue, and this is what's going on:

  • NavigationToolbar2._update_cursor() sets NavigationToolbar2._last_cursor only when the mouse moves and the current tool requires a different cursor than the current value of _last_cursor.
  • NavigationToolbar2._wait_cursor_for_draw_cm() resets the cursor to _last_cursor after drawing is finished, thus undoing any changes made through FigureCanvas.set_cursor().
  • Example scripts (1, 2) solve this by calling set_cursor() every time the mouse is moved. However, this doesn't work for the specific case of Cursors.MOVE on the macosx backend: the backend changes the open hand cursor to a closed hand when the mouse is pressed. Calling set_cursor() every mouse move resets it to an open hand, but not doing that resets it to _last_cursor instead.

I think the solution might be for the macosx backend's FigureCanvas_set_cursor() to map Cursors.MOVE to the closed hand cursor if the mouse is currently pressed. Unless anyone can think of a time when this would be undesired?

On a related note, @QuLogic, should _last_cursor and _wait_cursor_for_draw_cm() be moved from NavigationToolbar2 to FigureCanvas in line with #20620? Then set_cursor() could update _last_cursor not just for the toolbar, and only actually change the cursor when necessary, but I'm not sure if widgets updating the cursor constantly even has significant overhead on any backends. Though that would have the issue that if any use case for some reason changes the cursor while a toolbar tool is active, it would need to change the cursor back to the tool's cursor afterwards.

@greglucas
Copy link
Contributor

@daniilS lets keep the macosx issues discussed in the linked PR for that. I think this is a useful addition still and just needs a rebase at this point.

@QuLogic
Copy link
Member

QuLogic commented Jun 24, 2023

I think you might need to rebase, as there seems to be some extra commits here. We have some instructions for that here: https://matplotlib.org/devdocs/devel/development_workflow.html#rewriting-commit-history

@daniilS daniilS force-pushed the draggable-cursor branch 2 times, most recently from 80b0af1 to 8ce6c89 Compare July 7, 2023 14:11
@daniilS
Copy link
Contributor Author

daniilS commented Jul 7, 2023

Fixed the rebase. However, I found that this PR reveals a different issue with DraggableBase: when a figure or axes is removed, disconnect() never gets called, leaving the callbacks in place, so the mouse cursor keeps changing when hovering over the place where the legend used to be. An example (video shown below):

import matplotlib.pyplot as plt

line = plt.plot(range(3), label="line")[0]
leg = plt.legend(draggable=True, loc="upper center", fontsize="xx-large", mode="expand")

plt.show(block=False)
plt.pause(1)
plt.clf()
plt.show()
# cursor still changes when hovering over the top of the figure

I think a hook should be added somewhere to call disconnect() when the associated artist is removed, but I'm not sure where would be a good place.

draggable_bug.webm

@anntzer
Copy link
Contributor

anntzer commented Jul 24, 2023

Perhaps _Axes._remove_legend? (via _legend._remove_method)

@daniilS daniilS force-pushed the draggable-cursor branch 2 times, most recently from d76c7d9 to 0bcfe16 Compare July 25, 2023 00:34
@daniilS
Copy link
Contributor Author

daniilS commented Jul 25, 2023

@anntzer thanks, that pointed me towards what I think is the right place! It looks to me like the best solution is to deparent the legend together with other artists in _AxesBase.__clear() following #24627. @tacaswell, can I just check that I'm not overlooking anything in case the legend deliberately wasn't included in that commit?

@daniilS daniilS force-pushed the draggable-cursor branch from dd584b7 to a8d1677 Compare July 28, 2023 12:25
Comment on lines +1515 to +1520
if not (
self._check_still_parented()
and self.canvas.widgetlock.available(self)
and self.ref_artist.pickable()
):
return
Copy link
Member

@timhoffm timhoffm Aug 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the logic correct? If self.ref_artist.pickable() is False, we return. That means we never reach the original if self.got_artist: branch.

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.

6 participants