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

Skip to content

Doc: Fix Patheditor example #11431

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

Conversation

ImportanceOfBeingErnest
Copy link
Member

PR Summary

The path editor example errors when being run with an interactive backend, due to a recursion in drawing the elements.

This PR fixes this issue by not blitting inside the draw_event (because that happens before the screen update anyways).

Copy link
Contributor

@anntzer anntzer left a comment

Choose a reason for hiding this comment

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

I can't manage to trigger any error with the example as it is right now, and removing the blit line makes the example not work anymore on tkagg for me.

Anyone can dismiss the review if this problem is sorted out.

@ImportanceOfBeingErnest
Copy link
Member Author

Ok, seems this needs some more detailed bug report.

With Qt5Agg backend, py 3.6 on windows 8.1, running the example as script produces

This error (hidden for convenience)
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
QWidget::repaint: Recursive repaint detected
Traceback (most recent call last):
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    self.draw()
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    self.figure.draw(self.renderer)
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    return draw(artist, renderer, *args, **kwargs)
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    renderer, self, artists, self.suppressComposite)
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    a.draw(renderer)
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    return draw(artist, renderer, *args, **kwargs)
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    mimage._draw_list_compositing_images(renderer, self, ar
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    a.draw(renderer)
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    return draw(artist, renderer, *args, **kwargs)
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    ticks_to_draw = self._update_ticks(renderer)
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    tick_tups = list(self.iter_ticks())  # iter_ticks calls
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    majorLocs = self.major.locator()
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    return self.tick_values(vmin, vmax)
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    locs = self._raw_ticks(vmin, vmax)
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    nbins = np.clip(self.axis.get_tick_space(),
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    tick = self._get_tick(True)
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    return XTick(self.axes, 0, '', major=major, **tick_kw)
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    self.apply_tickdir(tickdir)
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    self.stale = True
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    self.stale_callback(self, val)
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    self.axes.stale = val
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    self.stale_callback(self, val)
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    self.figure.stale = val
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    self.stale_callback(self, val)
  File "d:\data\computer\entwicklung\python\matplotlib\sour
    if val and matplotlib.is_interactive() and not fig.canv
RecursionError: maximum recursion depth exceeded
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted

...this is hidden, collapsable content...

With TkAgg backend, py 3.6 on windows 8.1, running the example as script runs fine without error and produces the desired plot.

Removing the line self.canvas.blit(self.ax.bbox) as proposed here, lets the script run fine in TkAgg backend as well as Qt5Agg backend.

This led me to the conclusion that, similarly to the poly_editor example, one should not try to blit inside the draw_event callback. Logically this makes sense to me because there is no reason to blit if the figure is drawn anyways shortly afterwards.

@anntzer What kind of error do you get when running this with the line in question removed? Does the same happen for the poly_editor example as it is now?

@tacaswell
Copy link
Member

This is the race condition that just keeps giving....

@tacaswell tacaswell added this to the v2.2.3 milestone Jun 13, 2018
@anntzer
Copy link
Contributor

anntzer commented Jun 13, 2018

For me (linux/py3/tkagg), removing the line causes nothing to happen at all when attempting to drag a point.

@ImportanceOfBeingErnest
Copy link
Member Author

ImportanceOfBeingErnest commented Jun 18, 2018

Any conclusion? Should I better close this and open an issue about it?
For sure the example that crashes on Windows should not stay in the docs, unless there is a way to make it work again. I wonder why the other example would still run on both systems while there does not seem to be that much of a difference.

@anntzer
Copy link
Contributor

anntzer commented Jun 18, 2018

I think leaving this open is just as good as opening a separate issue.

@jklymak
Copy link
Member

jklymak commented Jul 3, 2018

Just marking as "Needs revision" so folks don't click on this as a PR that needs review, not as a spur to action....

@ImportanceOfBeingErnest
Copy link
Member Author

Keeping this as an unfinished/dead PR will probably rather cause confusion once someone revisists this in the future. So, I guess I will open an issue about it one of those days.

It's currently not clear (to me) why there is even a difference between the examples being run on windows and linux and this might well point towards a bigger underlying problem.

@QuLogic
Copy link
Member

QuLogic commented Apr 1, 2020

I cannot reproduce any error with Qt5Agg using current master.

@timhoffm
Copy link
Member

timhoffm commented May 3, 2020

I cannot reproduce the error either with:

  • Python 3.7.7
  • PyQt5 5.9.6
  • matplotlib 3.1.3

@ImportanceOfBeingErnest can you test on a more recent version yourself? Otherwise I propose to close this assuming fixed tue to @QuLogic and me not being able to reproduce it.

@ImportanceOfBeingErnest
Copy link
Member Author

The issue is still present.
Again let me mention that the same is applied to the poly_editor example which even has a comment on why:

self.ax.draw_artist(self.line)
# do not need to blit here, this will fire before the screen is
# updated

@ImportanceOfBeingErnest
Copy link
Member Author

No wait. This is actually fixed by #16028
Closing this.
Although I would actually be interested in knowing why the one example can live without a blit and the other not...

@ImportanceOfBeingErnest ImportanceOfBeingErnest deleted the fix-patheditor-example branch May 3, 2020 08:36
@QuLogic QuLogic removed this from the v2.2-doc milestone May 3, 2020
@anntzer
Copy link
Contributor

anntzer commented May 3, 2020

Actually in my hands the path_editor example now also works on tkagg without the blit; if others can confirm that perhaps we can just remove it.

@rcomer
Copy link
Member

rcomer commented Apr 1, 2024

I was just playing with the path_editor example and found that with QtAgg if I resize the window I get

QWidget::repaint: Recursive repaint detected
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
Segmentation fault (core dumped)

Removing the blit line fixes this for me. TkAgg works fine whether the blit line is there or not.

I am on Ubuntu 22.04 and tested this with main.

I was going to open a new issue but then found this. Maybe I should still open a new issue...

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.

8 participants