Skip to content
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

Animation._end_redraw() issue with event-driven animation #9153

Closed
wombatonfire opened this issue Sep 3, 2017 · 17 comments
Closed

Animation._end_redraw() issue with event-driven animation #9153

wombatonfire opened this issue Sep 3, 2017 · 17 comments
Labels
status: closed as inactive Issues closed by the "Stale" Github Action. Please comment on any you think should still be open. status: inactive Marked by the “Stale” Github Action

Comments

@wombatonfire
Copy link

Bug report

Bug summary

Animation._end_redraw() method, which is called after window resizing, always calls self._post_draw() with blit=False:

def _end_redraw(self, evt):
    # Now that the redraw has happened, do the post draw flushing and
    # blit handling. Then re-enable all of the original events.
    self._post_draw(None, False)
    self.event_source.start()
    self._fig.canvas.mpl_disconnect(self._resize_id)
    self._resize_id = self._fig.canvas.mpl_connect('resize_event',
                                                   self._handle_resize)

self._fig.canvas.draw_idle() is used directly in this case, and self._drawn_artists is ignored. In a scenario where the plot is updated only when new data points arrive, this leads to a blank window after resize and until you get new data point and a plot update function is executed.

Of course, I can override this behaviour, but the question is why not to call self._post_draw() here as it is called from other places:

self._post_draw(None, self._blit)

Doing this will respect already drawn artists if you resize the window before new data points arrive.

Matplotlib version

  • Operating System: Windows 10
  • Matplotlib Version: 2.0.2
  • Python Version: 2.7.13

Matplotlib and Python are installed as part of Anaconda 4.4.0.

@dopplershift
Copy link
Contributor

That was an explicit change came in #6339 to address some "glitches on resize on Mac/Qt".

So it seems like we may need to revert this. Can you cook up a simple example to replicate the incorrect behavior you're seeing?

@wombatonfire
Copy link
Author

Example. Python 2.7, Qt 5, PyQt5. GUI with a plot receives data points from a different thread every 3 seconds. Try to resize the window between plot updates, or after we received all the data points (10 in total). Then have a look at the DataAnimation class and uncomment _end_redraw() method. The issue will be gone.

@wombatonfire
Copy link
Author

wombatonfire commented Oct 7, 2017

@dopplershift, does the example work for you? Can you confirm the behaviour?

@dopplershift
Copy link
Contributor

I can reproduce the problem, and I can reproduce it even more easily with some of our simpler animation examples if I tune down the refresh.

Unfortunately, your solution with matplotlib 2.1 triggers a lot of warnings (and non-functional behavior) because that ends up calling draw() from within an existing draw call. This produces warnings like

QWidget::repaint: Recursive repaint detected

and

QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted

What we really need is a way to force a new draw after the other one completes...

@anntzer
Copy link
Contributor

anntzer commented Oct 25, 2017

#9505 should handle (or at least document...) most of the recursive repaint issues.

@dopplershift
Copy link
Contributor

I'm also wondering if we're going about this all wrong. I wonder if there's a way to just turn off blitting entirely when a resize happens, since with blitting off everything works fine. Then let blitting return to on after the resize is taken care of.

@dopplershift
Copy link
Contributor

@anntzer While I can confirm it works better on 2.1.x branch, I still definitely get messages. But I think the animation module is wrong in literally invoking recursive draws.

@dopplershift
Copy link
Contributor

I have a branch where I've changed how blit + resize is changed that seems like a much better approach. I think this is going to grow into a bit of a refactor to separate out how blitting is handled (too many if blits distributed through the code).

@tacaswell tacaswell added this to the v2.2 milestone Oct 30, 2017
@tacaswell
Copy link
Member

marked as 2.2 as @dopplershift says a big refactor is coming 😈

@wombatonfire
Copy link
Author

Hi,

I finally had to update Matplotlib and my workaround started to produce QWidget::repaint: Recursive repaint detected as it was expected.

Is there any other way of solving the original issue with a blank window after resize? Big refactoring didn't seem to help. 😆

@dopplershift
Copy link
Contributor

Sadly, big refactor is still half-baked on my hard disk. 😱

@wombatonfire
Copy link
Author

Do you think I can help somehow with this specific problem? Or is it too big and complex for someone not familiar with the codebase?

@dopplershift
Copy link
Contributor

You're welcome to take a look at my branch here: https://github.com/dopplershift/matplotlib/tree/anim-blit2

I know I found the blitting stuff to be a little tricky, mostly because we don't control when the GUI frameworks actually complete a draw.

@tacaswell
Copy link
Member

@wombatonfire What version are you using? I thought we had squashed all of the recursive re-paint issues....

@wombatonfire
Copy link
Author

@tacaswell The recursive re-paint issue appears if I override self._post_draw() in _end_redraw() and, as I understood, it is expected, it's not a matplotlib problem, but a problem of my workaround, which worked previously on v2.0.2.

The real problem for me is that I loose existing data on a real-time plot after resize, until new data points arrive. That's the core issue.

@tacaswell
Copy link
Member

That sounds like we are missing a "and re-draw the animated artsts" call just after we regenerate and capture the background.

@github-actions
Copy link

This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!

@github-actions github-actions bot added the status: inactive Marked by the “Stale” Github Action label Apr 17, 2023
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale May 17, 2023
@rcomer rcomer added the status: closed as inactive Issues closed by the "Stale" Github Action. Please comment on any you think should still be open. label May 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: closed as inactive Issues closed by the "Stale" Github Action. Please comment on any you think should still be open. status: inactive Marked by the “Stale” Github Action
Projects
None yet
Development

No branches or pull requests

5 participants