You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PyQGIS设置栅格图层样式:样式面板与TOC异常问题

问题:PyQGIS应用Matplotlib色带后,TOC值范围与样式面板未正确更新

我使用PyQGIS为单波段QgsRasterLayer应用Matplotlib自定义色带时,地图画布显示正常,但目录(TOC)中的值范围始终显示为0-255(而非图层实际极值),尽管色带本身显示正确;样式面板也一直保留上次使用的色带设置,即使重启QGIS也无法更新。如何让这些内容同步正确更新?

原测试代码:

from matplotlib import colormaps
import numpy as np

lyr = iface.activeLayer()
if isinstance(lyr, QgsRasterLayer):
    if lyr.bandCount() == 1:
        # define color map by name
        map = colormaps['viridis']

        # get min/max values
        stats = lyr.dataProvider().bandStatistics(1, QgsRasterBandStats.All)
        val_min = stats.minimumValue
        val_max = stats.maximumValue

        # limit number of color steps to 20
        if map.N > 20:
            colors = map(np.linspace(1, map.N, 20, dtype=np.int16))
        else:
            colors = map(range(1,map.N))
        colorsN = len(colors)

        # raster values for the color steps
        valList = np.linspace(val_min, val_max, colorsN)

        # making a colorRamp-list with
        colorsList = []
        for idx, col in enumerate(colors):
            qcol = QColor(int(col[0]*255), int(col[1]*255), int(col[2]*255))
            val = valList[idx]
            #print(val, qcol)
            colorsList.append( QgsColorRampShader.ColorRampItem(val, qcol) )

        # apply code
        fcn = QgsColorRampShader()
        fcn.setColorRampType(QgsColorRampShader.Interpolated)
        fcn.setColorRampItemList(colorsList)
        shader = QgsRasterShader()
        shader.setRasterShaderFunction(fcn)
        renderer = QgsSingleBandPseudoColorRenderer(lyr.dataProvider(), 1, shader)                
        lyr.setRenderer(renderer)
        lyr.renderer().createLegendNodes(QgsLayerTreeLayer(lyr.id()))

lyr.triggerRepaint()
lyr.emitStyleChanged()

解决方案

问题根源在于未正确同步渲染器的极值设置、图层统计信息缓存,以及样式面板的刷新机制。以下是修改后的代码,补充了关键同步步骤:

from matplotlib import colormaps
import numpy as np

lyr = iface.activeLayer()
if isinstance(lyr, QgsRasterLayer) and lyr.bandCount() == 1:
    # 加载Matplotlib色带
    cmap = colormaps['viridis']
    
    # 获取图层实际统计极值
    stats = lyr.dataProvider().bandStatistics(1, QgsRasterBandStats.All)
    val_min = stats.minimumValue
    val_max = stats.maximumValue
    
    # 限制色阶数量最多20个
    color_count = min(cmap.N, 20)
    # 直接用0-1范围采样色带,避免原代码索引错误
    colors = cmap(np.linspace(0, 1, color_count))
    
    # 生成对应值范围的色阶节点
    val_list = np.linspace(val_min, val_max, color_count)
    color_ramp_items = []
    for val, col in zip(val_list, colors):
        qcol = QColor(int(col[0]*255), int(col[1]*255), int(col[2]*255))
        color_ramp_items.append(QgsColorRampShader.ColorRampItem(val, qcol))
    
    # 配置颜色渐变Shader
    color_ramp_shader = QgsColorRampShader()
    color_ramp_shader.setColorRampType(QgsColorRampShader.Interpolated)
    color_ramp_shader.setColorRampItemList(color_ramp_items)
    # 关键:明确设置Shader的极值范围
    color_ramp_shader.setMinimumValue(val_min)
    color_ramp_shader.setMaximumValue(val_max)
    
    raster_shader = QgsRasterShader()
    raster_shader.setRasterShaderFunction(color_ramp_shader)
    
    # 创建并配置渲染器
    renderer = QgsSingleBandPseudoColorRenderer(lyr.dataProvider(), 1, raster_shader)
    # 关键:设置渲染器的分类极值
    renderer.setClassificationMin(val_min)
    renderer.setClassificationMax(val_max)
    
    lyr.setRenderer(renderer)
    
    # 关键:更新数据提供者的统计缓存,让TOC读取正确极值
    lyr.dataProvider().setUserMinimumValue(1, val_min)
    lyr.dataProvider().setUserMaximumValue(1, val_max)
    lyr.dataProvider().setStatistics(1, QgsRasterBandStats.All, stats, True)
    
    # 触发图层刷新与样式更新
    lyr.triggerRepaint()
    lyr.emitStyleChanged()
    # 强制刷新图层树的符号显示,同步样式面板
    iface.layerTreeView().refreshLayerSymbology(lyr.id())

关键修改说明

  • 修正色带采样逻辑:原代码用map.N索引采样易出错,改为直接用0-1范围采样Matplotlib色带,更稳定
  • 同步Shader与渲染器极值:通过setMinimumValue/MaximumValue和setClassificationMin/Max让渲染器明确值范围,避免默认使用0-255
  • 更新统计缓存:调用setUserMinimumValue等方法强制QGIS存储正确极值,解决TOC显示错误问题
  • 强制刷新图层树:refreshLayerSymbology确保样式面板和目录同步显示新色带

内容的提问来源于stack exchange,提问作者Leviathan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 12:27:32