[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