-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Switch the cursor to a busy cursor while redrawing. #6603
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
Switch the cursor to a busy cursor while redrawing. #6603
Conversation
6c8450c
to
1a816ae
Compare
On an vaguely related note, I noticed the methods |
... or we make it actually do something. It is fully functional and On Sat, Jun 18, 2016 at 4:48 AM, Antony Lee [email protected]
|
I am curious of the history when those methods were added and why. There are a surprising number if bread crumb trails in the codebase. |
Also, this is a huge UX improvement this should be backported to 2.0 |
Perhaps you're better than me at |
Are the Cairo backends also handled here? |
Good catch. A quick look seems to indicate that the Cairo backend does not override |
Maybe on the |
Done. The cursor switches to a spinwheel, but is not animated, for a reason I don't understand. Side notes:
|
@OceanWolf @fariza can you address the gtk questions? |
try: | ||
if toolbar: | ||
toolbar.set_cursor(cursors.WAIT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to fail with new tool manager, toolbar doesn't have a set_cursor method anymore.
I have to think in a clean way of doing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a completely different note... you are doing this to the AGG backend, a non-interactive backend. How does this code interact with the combined backends like GtkAgg and such? Would this code get called twice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I never got an answer about why this is being done for the AGG backend.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aye, but from what I gather set_cursor will move from the toolbar to the canvas.
I'm +1 on doing this now so that we get a clean PR, but @tacaswell disagrees.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@OceanWolf, was that a response to my question? I am not sure how your response applies, since the AGG backend has a canvas, too. Why is there any cursor-handling code for the agg backend?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, It applies only in the sense that the code here has already been slated for removal. Only a partial answer to your question.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, missed the comments.
The reason to put this here is the same reason why canvas.toolbar exists on all canvases (possibly None) rather than only on interactive ones: because there is no InteractiveCanvas class in the hierarchy :-) (Note that this is orthogonal with the toolmanager question)
Apparently unused ever since they were added. See original discussion in matplotlib#6603.
Apparently unused and with no effect ever since they were added. See original discussion in matplotlib#6603.
Right now it looks like Qt4Agg Qt5Agg GtkCairo and Gtk3Cairo all work (I don't see the warning mentioned in #6603 (comment) anymore). In theory Tk and WX "should" be supported too but don't actually work. Could we push this forward with just support for these backends? |
f2f72f6
to
5d06137
Compare
Rebased. Now works on py3: qt4 qt5 tk gtk3 and py2: wx gtk (haven't tested other combos). See the latest commit for the reason (we needed to trigger the event loop on some backends). |
@fariza What owns the cursor in the new tool model? It does make a certain amount of sense for the toolbar to do so (as it holds the other things that change the state of the cursor. The other logical option is for the manager to own it. Not sure I like putting this all the way down in A decorator like: def wating_cursor(meth):
@contextlib.contextmanager
def spin_cursor(manager):
manager and manager.set_cursor(cursor.WAIT)
try:
yield
finally:
manager and manager.set_cursor(cursor.POINTER)
@functools.wraps(meth)
def inner(self, *args, **kwargs):
mager = getattr(self, 'manager', None)
with spin_cursor(manager):
return meth(self, *args, **kwarg) would make this easy and safe to apply. |
@anntzer is the problem of returning to previously selected cursor solved? @tacaswell the cursors doesn't belong to the toolbar, right now there is a tool that sets the cursor when in axes We can just trigger an event to inform the tool that we are waiting. But this seems a little bit overkill and maybe too much resources? |
Now it is :) see latest commit |
@tacaswell I'm not convinced that adding a contextmanager around each and every call to draw() from an interactive backend is the solution (e.g. people sometimes call figure.canvas.draw() themselves)... or I guess interactive backends could derive from a common InteractiveCanvas class (earlier than FigureCanvasAgg in the MRO) which defines
but then you're actually relying on multiple inheritance to do your job correctly (which I am actually totally fine with). |
@@ -538,7 +539,7 @@ def set_message(self, s): | |||
|
|||
def set_cursor(self, cursor): | |||
self.canvas.get_property("window").set_cursor(cursord[cursor]) | |||
#self.canvas.set_cursor(cursord[cursor]) | |||
Gtk.main_iteration() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are you adding this cal to Gtk.main_iteration
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because otherwise the cursor is actually not set on the GUI (see docstring changed in CanvasBase.set_cursor). Basically, what happens is
Notification that a redraw is necessary.
Redraw starts and cursor is set.
[possibly long computation]
Return to GUI thread.
Note that the GUI event loop doesn't get to run between [cursor is set] and [possibly long computation], so depending on the details of the toolkit, the cursor change may not actually appear to the user before the end of the computation. Letting the GUI event loop run once allows it to change the cursor. (And upon testing, I see that Qt does not need this, probably because its version of setCursor triggers(?) the event loop.)
For the toolmanager, I think it can be done using the |
@tacaswell what would be the problem moving |
(fwiw I agree that it may make sense to allow ourselves to change the cursor even if there is no toolbar (ie in some embedding cases)) |
The canvas class makes more sense than the manager class so that direct embeddings can take advantage of it, but we will have to be careful to not mess with anything end-user may already be doing with the cursor. |
We are already messing up with the cursor if the embedding includes a
toolbar.
We could e.g. say "mpl may modify the cursor state. If you do not wish
this to happen, override the canvas.set_cursor method to lambda cursor:
None".
On Jun 11, 2017 7:47 PM, "Thomas A Caswell" <[email protected]> wrote:
The canvas class makes more sense than the manager class so that direct
embeddings can take advantage of it, but we will have to be careful to not
mess with anything end-user may already be doing with the cursor.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#6603 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABQv3mw_Dc-EGGMrwcZRZ60nsQYf5apdks5sDKbIgaJpZM4I45VE>
.
|
Fair enough. |
7ab48cd
to
6c6cab4
Compare
Rebased. |
So we are not moving the |
We can do that later, I think it is worth getting the busy-spinner in now. |
is this ready to go? looks like features are there...time to merge this 1-year-old PR? :-) |
(I think this is good to go.) |
To test, plot e.g. `plot(rand(100000))` and zoom in manually (the redraw should take some time). The cursor should switch to a "busy" cursor (e.g. spinwheel). The switch doesn't seem to happen under the Tk and WX backends, probably due to some event loop intricacies I don't understand.
The wait cursor is not animated, though.
6c6cab4
to
d1516e6
Compare
rebased |
Allowing myself to mark this as release critical as it's been around for very long, it's been approved, and @tacaswell says it's "a huge UX improvement" :-) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having the feature itself is a great improvement. Refactoring to put this in a more logical place, while nice, is not a reason to hold up this PR.
I am happy this went in 👍 |
To test, plot e.g.
plot(rand(100000))
and zoom in manually (theredraw should take some time). The cursor should switch to a "busy"
cursor (e.g. spinwheel). The switch doesn't seem to happen under the
Tk and WX backends, probably due to some event loop intricacies I don't
understand.