Strange resize behaviour for qt backend

Hi again,

Ole Streicher <ole-usenet-spam@...361...> writes:

could anyone reproduce this problem and/or has a solution for it? Is
there anything wrong with my code?

after some discussion on the PyQt mailing list, I found the cause of the
problem:

In matplotlib.FigureCanvasQTAgg, the following piece of code is called
on a resizeEvent:

def draw( self ):

    # ... some internal code

    # Added following line to improve realtime pan/zoom on windows:
    QtGui.qApp.processEvents()

This makes the problem clear:
- if we resize the window quickly, several resizeEvents are created and
  are in the event queue of Qt
- the first one gets processed by the QVBoxLayout which starts the
  processing in its first (matplotlib) widget.
- the matplotlib widget does what it should and at some point calls
  matplotlib.FigureCanvasQTAgg.draw(self).
  - this starts the processing of the next event in the queue which is
    the next (2nd) resize event. BUT: we are still in the processing of
    the first event!!!
  - the 2nd event goes to the QVBoxLayout, from there to the matlotlib
    widget (eventually starting some recursive behaviour here)
  - if the 2nd event is finished, QVBoxLayout sends it to its other widget
    (the scrollbar). The scrollbar is resized according to the *2nd event*.
- if the processing of the 2nd event was finished and no more events are
  in the queue, the matplotlib.FigureCanvasQTAgg.draw() finishes
- at the end, this will finish the processing of the first resize event
  in the matplotlib widget and start the *first resize event* for the
  scrollbar

This is exactly the behaviour that I observed. It is caused by the
QtGui.qApp.processEvents() call in the draw() function.

So, I think this is clearly a bug in matplotlib:
QtGui.qApp.processEvents() should not be called while processing another
event.

Best regards

Ole

Thank you Ole for tracking this down. I have submitted a change in svn 7250 which I think fixes this problem. However, the offending line was originally added to improve performance of panning and zooming on windows. I have tested the changes on 64-bit windows vista, and panning and zooming appear to be responsive, but I would appreciate it if other windows users would test as well. Just save the attached files into your site-packages/matplotlib/backends directory to test the new code.

Thanks,
Darren

backend_qt4.py (20.5 KB)

backend_qt4agg.py (4.69 KB)

···

On Wed, Jul 8, 2009 at 3:10 AM, Ole Streicher <ole-usenet-spam@…361…> wrote:

Hi again,

Ole Streicher <ole-usenet-spam@…361…> writes:

could anyone reproduce this problem and/or has a solution for it? Is

there anything wrong with my code?

after some discussion on the PyQt mailing list, I found the cause of the

problem:

In matplotlib.FigureCanvasQTAgg, the following piece of code is called

on a resizeEvent:

def draw( self ):

# ... some internal code



# Added following line to improve realtime pan/zoom on windows:

QtGui.qApp.processEvents()

This makes the problem clear:

  • if we resize the window quickly, several resizeEvents are created and

    are in the event queue of Qt

  • the first one gets processed by the QVBoxLayout which starts the

    processing in its first (matplotlib) widget.

  • the matplotlib widget does what it should and at some point calls

    matplotlib.FigureCanvasQTAgg.draw(self).

    • this starts the processing of the next event in the queue which is

      the next (2nd) resize event. BUT: we are still in the processing of

      the first event!!!

    • the 2nd event goes to the QVBoxLayout, from there to the matlotlib

      widget (eventually starting some recursive behaviour here)

    • if the 2nd event is finished, QVBoxLayout sends it to its other widget

      (the scrollbar). The scrollbar is resized according to the 2nd event.

  • if the processing of the 2nd event was finished and no more events are

    in the queue, the matplotlib.FigureCanvasQTAgg.draw() finishes

  • at the end, this will finish the processing of the first resize event

    in the matplotlib widget and start the first resize event for the

    scrollbar

This is exactly the behaviour that I observed. It is caused by the

QtGui.qApp.processEvents() call in the draw() function.

So, I think this is clearly a bug in matplotlib:

QtGui.qApp.processEvents() should not be called while processing another

event.