[Qgis-developer] [Qgis-user] WMS Rendering Problems
Tom Elwertowski
telwertowski at comcast.net
Sun Nov 4 01:51:46 EDT 2007
Marco Hugentobler wrote:
> I think that the WMS refresh problem is due to a problem with
> QGraphicsView/QGraphicsRectItem, which I tried to adress with r7316. This fix
> works for me on Kubuntu7.10, Win XP (msys) and Mac (G4).
>
> From what I can see, the synchronous requesting works as expected and is left
> at the time QHttp sends the done() signal (once all the requested data is
> available). The painting is then done into QImage, which I think is plattform
> independent (software rendering).
>
> Asynchronous requesting of WMS layers could still be a possibility for the
> future. Maybe combined with Tims idea of a composite manager? I think that
> such functionality should be developed in a branch as there is a high risk of
> side effects.
Hi Marco,
r7316 doesn't fix the Mac WMS rendering problem; I am also using a Mac
G4. To reproduce the bug, open a WMS layer and then resize or maximize
the window. The layer is cleared and not redrawn. Other widgets such as
the status and tool bars are sometimes drawn at incorrect locations too.
Resizing a window by dragging the size control is a "gold standard" for
testing Mac drawing code. If there are problems, they are most likely to
show up while resizing a window.
The problem is that the WMS implementation is not "Qt processEvent
safe." Moving to asynchronous network events is one way to make the code
processEvent safe. Moving the synchronous transfer outside the draw
event might also work. Using threads for drawing is probably the best
solution. I chose the asynchronous approach because it seemed closest to
a bug fix than a redesign.
This is the problematic sequence of events:
1. Resize window
2. WMS provider initiates draw event.
3. draw routine discovers layer needs refresh from WMS server.
4. draw routine issues network request.
5. QgsHttpTransaction calls processEvents so that network request can
leave local machine.
6. processEvents now runs other events while waiting for the remote
response.
7. there are drawing events pending due to setStatus signals from
QgsHttpTransaction and QgsRasterLayer as well as for drawing the
overview canvas. If a drag resize is in progress, there are also
additional draw events due to the continued resizing of the main canvas.
This is the bug -- a Mac draw event cannot be interrupted by another
draw event.
8. eventually we resume interrupted draw events which are not able to be
resumed.
Here is the Mac terminal log:
Warning: QWidget::repaint: Recursive repaint detected
Warning: QCoreGraphicsPaintEngine::begin: Painter already active
Warning: QPainter::begin(): Returned false
Warning: QPainter::end: Painter not active, aborted
followed by many of:
Warning: QWidget: It is dangerous to leave painters active on a widget
outside of the PaintEvent
My guess is that the begin() of the second draw event is ignored as
superfluous because the painter is already active. The second draw event
then draws and successfully closes the painter. At this point, the
resumed first draw is attempting to draw into an inactive painter.
If we don't change anything, we need to tell users that QGIS/Mac does
not support resizing or maximizing project windows containing WMS layers.
I have been thinking along the same lines as Tim's composite manager but
that's a bigger project than I want to do right now. It's probably best
left for QGIS 1.1. For now, we should see if nested draw events can be
eliminated without a major redesign.
It would also be nice to have some development guidelines about
processEvents since this problem keeps reappearing. A good rule would be
that calls to processEvents cannot be made while drawing is in progress.
Another good rule is not to allow QtPainter warnings in code which
appears to work. These usually indicate code that is not cross-platform
safe.
Tom
More information about the Qgis-developer
mailing list