diff --git a/python/gui/qgsmapcanvas.sip b/python/gui/qgsmapcanvas.sip index aaf7ff34735..ddcfbe4100d 100644 --- a/python/gui/qgsmapcanvas.sip +++ b/python/gui/qgsmapcanvas.sip @@ -30,6 +30,7 @@ class QgsMapCanvas : QGraphicsView bool isCachingEnabled() const; void clearCache(); void refreshAllLayers(); + void waitWhileRendering(); void setParallelRenderingEnabled( bool enabled ); bool isParallelRenderingEnabled() const; void setMapUpdateInterval( int timeMilliseconds ); diff --git a/src/gui/qgsmapcanvas.cpp b/src/gui/qgsmapcanvas.cpp index 4615f6972d0..8f0504f46cb 100644 --- a/src/gui/qgsmapcanvas.cpp +++ b/src/gui/qgsmapcanvas.cpp @@ -2016,6 +2016,14 @@ void QgsMapCanvas::refreshAllLayers() refresh(); } +void QgsMapCanvas::waitWhileRendering() +{ + while ( mRefreshScheduled || mJob ) + { + QgsApplication::processEvents(); + } +} + void QgsMapCanvas::setSegmentationTolerance( double tolerance ) { mSettings.setSegmentationTolerance( tolerance ); diff --git a/src/gui/qgsmapcanvas.h b/src/gui/qgsmapcanvas.h index f42bf1b1b5b..34264985a0b 100644 --- a/src/gui/qgsmapcanvas.h +++ b/src/gui/qgsmapcanvas.h @@ -128,6 +128,17 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView //! @note added in 2.9 void refreshAllLayers(); + /** + * Blocks until the rendering job has finished. + * + * In almost all cases you do NOT want to call this, as it will hang the UI + * until the rendering job is complete. It's included in API solely for + * unit testing and standalone python scripts. + * + * @note added in QGIS 3.0 + */ + void waitWhileRendering(); + //! Set whether the layers are rendered in parallel or sequentially //! @note added in 2.4 void setParallelRenderingEnabled( bool enabled ); diff --git a/tests/src/python/test_qgsmapcanvas.py b/tests/src/python/test_qgsmapcanvas.py index 99b93e6a2ec..f4d75661c20 100644 --- a/tests/src/python/test_qgsmapcanvas.py +++ b/tests/src/python/test_qgsmapcanvas.py @@ -58,13 +58,10 @@ class TestQgsMapCanvas(unittest.TestCase): canvas.setLayers([layer]) canvas.setExtent(QgsRectangle(10, 30, 20, 35)) canvas.show() - # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() - while canvas.isDrawing(): - app.processEvents() - + canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas)) # add polygon to layer @@ -83,10 +80,7 @@ class TestQgsMapCanvas(unittest.TestCase): # refresh canvas canvas.refresh() - while not canvas.isDrawing(): - app.processEvents() - while canvas.isDrawing(): - app.processEvents() + canvas.waitWhileRendering() # now we expect the canvas check to fail (since they'll be a new polygon rendered over it) self.assertFalse(self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas)) @@ -110,9 +104,7 @@ class TestQgsMapCanvas(unittest.TestCase): # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() - while canvas.isDrawing(): - app.processEvents() - + canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas)) # add polygon to layer @@ -210,9 +202,7 @@ class TestQgsMapCanvas(unittest.TestCase): # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() - while canvas.isDrawing(): - app.processEvents() - + canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # add some styles @@ -223,18 +213,12 @@ class TestQgsMapCanvas(unittest.TestCase): layer.styleManager().addStyleFromLayer('style2') canvas.refresh() - while not canvas.isDrawing(): - app.processEvents() - while canvas.isDrawing(): - app.processEvents() + canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme2', 'theme2', canvas)) layer.styleManager().setCurrentStyle('style1') canvas.refresh() - while not canvas.isDrawing(): - app.processEvents() - while canvas.isDrawing(): - app.processEvents() + canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # ok, so all good with setting/rendering map styles @@ -258,18 +242,12 @@ class TestQgsMapCanvas(unittest.TestCase): canvas.setTheme('theme2') canvas.refresh() - while not canvas.isDrawing(): - app.processEvents() - while canvas.isDrawing(): - app.processEvents() + canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme2', 'theme2', canvas)) canvas.setTheme('theme1') canvas.refresh() - while not canvas.isDrawing(): - app.processEvents() - while canvas.isDrawing(): - app.processEvents() + canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # add another layer @@ -286,17 +264,11 @@ class TestQgsMapCanvas(unittest.TestCase): # rerender canvas - should NOT show new layer canvas.refresh() - while not canvas.isDrawing(): - app.processEvents() - while canvas.isDrawing(): - app.processEvents() + canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # test again - this time refresh all layers canvas.refreshAllLayers() - while not canvas.isDrawing(): - app.processEvents() - while canvas.isDrawing(): - app.processEvents() + canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # add layer 2 to theme1 @@ -305,10 +277,7 @@ class TestQgsMapCanvas(unittest.TestCase): QgsProject.instance().mapThemeCollection().update('theme1', theme1) canvas.refresh() - while not canvas.isDrawing(): - app.processEvents() - while canvas.isDrawing(): - app.processEvents() + canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme3', 'theme3', canvas)) # change the appearance of an active style @@ -320,21 +289,14 @@ class TestQgsMapCanvas(unittest.TestCase): QgsProject.instance().mapThemeCollection().update('theme1', theme1) canvas.refresh() - while not canvas.isDrawing(): - app.processEvents() - while canvas.isDrawing(): - app.processEvents() + canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme3', 'theme3', canvas)) layer2.styleManager().setCurrentStyle('style4') sym3 = QgsFillSymbol.createSimple({'color': '#b200b2'}) layer2.renderer().setSymbol(sym3) canvas.refresh() - - while not canvas.isDrawing(): - app.processEvents() - while canvas.isDrawing(): - app.processEvents() + canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme4', 'theme4', canvas)) # try setting layers while a theme is in place @@ -342,20 +304,14 @@ class TestQgsMapCanvas(unittest.TestCase): canvas.refresh() # should be no change... setLayers should be ignored if canvas is following a theme! - while not canvas.isDrawing(): - app.processEvents() - while canvas.isDrawing(): - app.processEvents() + canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme4', 'theme4', canvas)) # setLayerStyleOverrides while theme is in place canvas.setLayerStyleOverrides({layer2.id(): 'original'}) # should be no change... setLayerStyleOverrides should be ignored if canvas is following a theme! canvas.refresh() - while not canvas.isDrawing(): - app.processEvents() - while canvas.isDrawing(): - app.processEvents() + canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme4', 'theme4', canvas)) def canvasImageCheck(self, name, reference_image, canvas):