Re: [PyQt] Re: question about resizing behavior

2009-07-07 Thread Brian Zambrano
Hi guys,

I'm also working with PyQt and matplotlib, and reported some weird resize
behavior on the matplotlib mailing list a few days ago.  I dug around a bit
and thought that something was going on with QtGui.qApp.processEvents(), but
it's nice to see that someone actually took the time to *really* understand
what's going onnice work Ole!

I'm on a Mac with OS X 10.5.7, and see some different behavior from you guys
(I think) because the attached code worked fine for me.

In any case, I'll follow this thread on the MPL list, and would be happy to
help out get this fixed.

BZ

On Tue, Jul 7, 2009 at 9:48 AM, Darren Dale  wrote:

> Hi Ole,
>
> On Tue, Jul 7, 2009 at 11:33 AM, Ole Streicher wrote:
>
>> Hi again,
>>
>> So, I think this is clearly a bug in matplotlib:
>> QtGui.qApp.processEvents() should not be called while processing another
>> event.
>>
>> Darren, I dont know your position with respect to matplotlib: are you a
>> developer and thus aware of the bug or shall I post this again on the
>> matplotlib mailing list?
>>
>
> I am a developer, but I think it would be good to post your summary there
> at the matplotlib mailing list so we can continue this discussion there.
>
> Darren
>
>
___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

Re: [PyQt] Re: question about resizing behavior

2009-07-07 Thread Darren Dale
Hi Ole,

On Tue, Jul 7, 2009 at 11:33 AM, Ole Streicher wrote:

> Hi again,
>
> Darren Dale  writes:
> > Nice demonstration of the problem Ole. I notice that if, after
> > resizing, I pause briefly before releasing the mouse button, the
> > scroll bar is more likely to resize properly. The problem is much more
> > apparent if I release the mouse button immediately after resizing or
> > while still dragging the window edge.
>
> I already created a Qt bug report for that (issue number #255433, not
> public
> for some reason). They asked me to compile a C++ only variant of the
> bug.
>
> However, I could not reproduce the problem in C++: the events occure here
> always in-order independent of the processing times in the (simulated)
> inner widget resize time.
>
> I could also not reproduce the bug in PyQt4 without matplotlib by
> replacing the FigureCanvasQTAgg with a QFrame and adding some random
> sleep to the resize function.
>
> But, with some stacktracing, I found the reason:
>
> 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 described in my first posting. 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.
>
> Darren, I dont know your position with respect to matplotlib: are you a
> developer and thus aware of the bug or shall I post this again on the
> matplotlib mailing list?
>

I am a developer, but I think it would be good to post your summary there at
the matplotlib mailing list so we can continue this discussion there.

Darren
___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

[PyQt] Re: question about resizing behavior

2009-07-07 Thread Ole Streicher
Hi again,

Darren Dale  writes:
> Nice demonstration of the problem Ole. I notice that if, after
> resizing, I pause briefly before releasing the mouse button, the
> scroll bar is more likely to resize properly. The problem is much more
> apparent if I release the mouse button immediately after resizing or
> while still dragging the window edge.

I already created a Qt bug report for that (issue number #255433, not public
for some reason). They asked me to compile a C++ only variant of the
bug.

However, I could not reproduce the problem in C++: the events occure here
always in-order independent of the processing times in the (simulated)
inner widget resize time.

I could also not reproduce the bug in PyQt4 without matplotlib by
replacing the FigureCanvasQTAgg with a QFrame and adding some random
sleep to the resize function. 

But, with some stacktracing, I found the reason:

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 described in my first posting. 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.

Darren, I dont know your position with respect to matplotlib: are you a
developer and thus aware of the bug or shall I post this again on the
matplotlib mailing list?

Best regards

Ole

___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt


Re: [PyQt] Re: question about resizing behavior

2009-07-07 Thread Darren Dale
On Tue, Jul 7, 2009 at 2:50 AM, Ole Streicher wrote:

> Hi Darren,
>
> Darren Dale  writes:
> > Nice demonstration of the problem Ole. I notice that if, after
> > resizing, I pause briefly before releasing the mouse button, the
> > scroll bar is more likely to resize properly. The problem is much more
> > apparent if I release the mouse button immediately after resizing or
> > while still dragging the window edge.
>
> Unfortunately the user will not be aware of that :-(
>
> Do you count it as a bug in matplotlib, in PyQt, or in Qt?


I don't know, that's why I posted here asking for help. So far we have only
described what is the problem.

Darren
___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

[PyQt] Re: question about resizing behavior

2009-07-06 Thread Ole Streicher
Hi Darren,

Darren Dale  writes:
> Nice demonstration of the problem Ole. I notice that if, after
> resizing, I pause briefly before releasing the mouse button, the
> scroll bar is more likely to resize properly. The problem is much more
> apparent if I release the mouse button immediately after resizing or
> while still dragging the window edge.

Unfortunately the user will not be aware of that :-(

Do you count it as a bug in matplotlib, in PyQt, or in Qt?

Regards

Ole

___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt


Re: [PyQt] Re: question about resizing behavior

2009-07-06 Thread Darren Dale
On Fri, Jul 3, 2009 at 3:37 AM, Ole Streicher wrote:

> Hello Darren,
>
> Darren Dale  writes:
> > Somebody reported some strange resizing behavior at the matplotlib
> mailing
> > list.
>
> The "somebody" was me :-)
>
> Here some additional information:
>
> If you printout the resize (overwritten) events of the scrollbar and the
> matplotlib widgets (see code below), you will see that sometimes the
> events are not processed in-order:
>
> ScrollBar start 640
> ScrollBar   end 640
>  Diagram start 640
>  Diagram   end 640
>
> occurs when I just started, which is correct. But when one changes the
> horizontal size, the following happens (printouts which obviously belong
> to the same resize event are marked with the same number of stars):
>
> * Diagram start 633
> **Diagram start 608
> [...]
> **Diagram   end 608
> **  ScrollBar start 608
> **  ScrollBar   end 608
> * Diagram   end 633
> *   ScrollBar start 633
> *   ScrollBar   end 633
>
> What you see is that
>
> - the matplotlib FigureCanvasQTAgg gets its first resize event
> - during its processing inside FigureCanvasQTAgg a second event
>  occurred
> - this second event is processed *faster* by FigureCanvasQTAgg than
>  the first event
> - thus, the second event occurs *first* on the scrollbar
> - the first resize event only occurs after the second on the scrollbar
> - this leads to a wrong size of the scrollbar
> - this may occur even nested (removed "[...]" in the printout above)
>
> This may be a bug in FigureCanvasQTAgg (it is not synchonized in the
> processing of resize events, allowing events to bypass), or in
> Qt/QVBoxLayout (same argument there). I am not deep enough inside Qt to
> know the API details here.
>
> Best regards
>
> Ole
> -8<--
> import sys
>
> from PyQt4 import QtGui, QtCore
> from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg
> from matplotlib.figure import Figure
>
> class MyDiagram(FigureCanvasQTAgg):
>def __init__(self, fig):
>FigureCanvasQTAgg.__init__(self, fig)
>
>def resizeEvent(self, event):
>print '  Diagram start', event.size().width()
>FigureCanvasQTAgg.resizeEvent(self, event)
>print '  Diagram   end', event.size().width()
>
>
> class MyScrollBar(QtGui.QScrollBar):
>def __init__(self, parent):
>QtGui.QScrollBar.__init__(self, QtCore.Qt.Horizontal, parent)
>
>def resizeEvent(self, event):
>print 'ScrollBar start', event.size().width()
>QtGui.QScrollBar.resizeEvent(self, event)
>print 'ScrollBar   end', event.size().width()
>
> class DiagramWidget(QtGui.QWidget):
>   def __init__(self, parent=None):
>   QtGui.QWidget.__init__(self, parent)
>
>self.scrollbar = MyScrollBar(self)
>
>   fig = Figure()
>   axes = fig.add_subplot(111)
>   axes.plot(xrange(100))
>self.diagram = MyDiagram(fig)
>self.diagram.setParent(self)
>
>   layout = QtGui.QVBoxLayout(self)
>   self.setLayout(layout)
>   layout.addWidget(self.diagram)
>   layout.addWidget(self.scrollbar)
>
> a = QtGui.QApplication(sys.argv)
> w = DiagramWidget()
> w.show()
> a.exec_()
>
> -8<--
>


Nice demonstration of the problem Ole. I notice that if, after resizing, I
pause briefly before releasing the mouse button, the scroll bar is more
likely to resize properly. The problem is much more apparent if I release
the mouse button immediately after resizing or while still dragging the
window edge.

I also tried adding a call to qApp.processEvents() in
FigureCanvasQT.resizeEvent, and that seemed to make the problem less
frequent, but the problem still exists.

Darren
___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

[PyQt] Re: question about resizing behavior

2009-07-03 Thread Ole Streicher
Hello Darren,

Darren Dale  writes:
> Somebody reported some strange resizing behavior at the matplotlib mailing
> list. 

The "somebody" was me :-)

Here some additional information:

If you printout the resize (overwritten) events of the scrollbar and the
matplotlib widgets (see code below), you will see that sometimes the
events are not processed in-order:

ScrollBar start 640
ScrollBar   end 640
  Diagram start 640
  Diagram   end 640

occurs when I just started, which is correct. But when one changes the
horizontal size, the following happens (printouts which obviously belong
to the same resize event are marked with the same number of stars):

* Diagram start 633
**Diagram start 608 
[...]
**Diagram   end 608
**  ScrollBar start 608
**  ScrollBar   end 608
* Diagram   end 633
*   ScrollBar start 633
*   ScrollBar   end 633

What you see is that

- the matplotlib FigureCanvasQTAgg gets its first resize event
- during its processing inside FigureCanvasQTAgg a second event
  occurred
- this second event is processed *faster* by FigureCanvasQTAgg than 
  the first event
- thus, the second event occurs *first* on the scrollbar
- the first resize event only occurs after the second on the scrollbar
- this leads to a wrong size of the scrollbar
- this may occur even nested (removed "[...]" in the printout above)

This may be a bug in FigureCanvasQTAgg (it is not synchonized in the
processing of resize events, allowing events to bypass), or in
Qt/QVBoxLayout (same argument there). I am not deep enough inside Qt to
know the API details here.

Best regards

Ole
-8<--
import sys

from PyQt4 import QtGui, QtCore
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg
from matplotlib.figure import Figure

class MyDiagram(FigureCanvasQTAgg):
def __init__(self, fig):
FigureCanvasQTAgg.__init__(self, fig)

def resizeEvent(self, event):
print '  Diagram start', event.size().width()
FigureCanvasQTAgg.resizeEvent(self, event)
print '  Diagram   end', event.size().width()


class MyScrollBar(QtGui.QScrollBar):
def __init__(self, parent):
QtGui.QScrollBar.__init__(self, QtCore.Qt.Horizontal, parent)

def resizeEvent(self, event):
print 'ScrollBar start', event.size().width()
QtGui.QScrollBar.resizeEvent(self, event)
print 'ScrollBar   end', event.size().width()

class DiagramWidget(QtGui.QWidget):
   def __init__(self, parent=None):
   QtGui.QWidget.__init__(self, parent)

   self.scrollbar = MyScrollBar(self)

   fig = Figure()
   axes = fig.add_subplot(111)
   axes.plot(xrange(100))
   self.diagram = MyDiagram(fig)
   self.diagram.setParent(self)

   layout = QtGui.QVBoxLayout(self)
   self.setLayout(layout)
   layout.addWidget(self.diagram)
   layout.addWidget(self.scrollbar)

a = QtGui.QApplication(sys.argv)
w = DiagramWidget()
w.show()
a.exec_()

-8<--

___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt