I'm trying to create a QGIS app using Python, where some layers are only visible at certain scales.
My code for the renderer is:
ROAD_RULES = (('Freeway', "CLASS_CODE = 0", 'dark green', 0.2, Qt.SolidLine, None),
('Main', "CLASS_CODE IN (1, 2, 3)", 'black', 0.2, Qt.SolidLine, None),
('Minor', "CLASS_CODE IN (4, 5)", 'dark gray', 0.15, Qt.SolidLine, (0, 2000000000)),
('Track', "CLASS_CODE IN (6, 7, 11, 12)", 'dark gray', 0.15, Qt.DashLine, (0, 2000000000)),
('Proposed', "CLASS_CODE = 9", 'gray', 0.15, Qt.DotLine, (0, 2000000000)))
# roads
# create new rule-based renderer and get root rule
symbol = QgsSymbolV2.defaultSymbol(self.roadLayer.geometryType())
renderer = QgsRuleBasedRendererV2(symbol)
root_rule = renderer.rootRule()
# based on rules, create clones and set their details
for label, expression, color_name, width, style, scale in ROAD_RULES:
rule = root_rule.children()[0].clone()
rule.setLabel(label)
rule.setFilterExpression(expression)
rule.symbol().deleteSymbolLayer(0)
symbol_layer = QgsSimpleLineSymbolLayerV2()
symbol_layer.setColor(QColor(color_name))
symbol_layer.setWidth(width)
symbol_layer.setPenStyle(style)
rule.symbol().appendSymbolLayer(symbol_layer)
if scale is not None:
rule.setScaleMinDenom(scale[0])
rule.setScaleMaxDenom(scale[1])
root_rule.appendChild(rule)
# delete default rule and apply renderer
root_rule.removeChildAt(0)
self.roadLayer.setRendererV2(renderer)
This works OK as long as I only zoom in and out of my map canvas using self.mapCanvas.zoomIn() and self.mapCanvas.zoomOut() methods. But if I zoom in and out using the mouse wheel, or if I pan, the scale changes and the maximum and minimum scales no longer work as intended.
When I say 'the scale changes', I mean that even when the map later looks the same on screen, mapCanvas.scale() will report a different scale figure (sometimes orders of magnitude different).
Is there a way to stop this, so that scale-dependent layers operate consistently in my app as they would in QGIS itself?