[{"data":1,"prerenderedAt":1516},["ShallowReactive",2],{"doc:\u002Fpyqgis-cartography-visualization\u002Fmap-canvas-and-image-export\u002Fset-map-canvas-background-color-pyqgis":3},{"id":4,"title":5,"body":6,"description":1505,"extension":1506,"meta":1507,"navigation":255,"path":1512,"seo":1513,"stem":1514,"__hash__":1515},"docs\u002Fpyqgis-cartography-visualization\u002Fmap-canvas-and-image-export\u002Fset-map-canvas-background-color-pyqgis\u002Findex.md","Set the Map Canvas Background Colour in PyQGIS",{"type":7,"value":8,"toc":1492},"minimark",[9,13,22,31,185,190,216,220,223,303,329,332,336,346,542,553,557,560,656,672,808,812,815,936,957,961,964,1064,1067,1209,1229,1233,1239,1301,1308,1312,1367,1371,1380,1384,1400,1410,1434,1440,1446,1452,1461,1465,1488],[10,11,5],"h1",{"id":12},"set-the-map-canvas-background-colour-in-pyqgis",[14,15,16,17,21],"p",{},"The background is the colour behind every layer, and it is set in three different places depending on what you are doing: on the canvas widget for the on-screen view, on ",[18,19,20],"code",{},"QgsMapSettings"," for a render job, and in the project for the setting that persists. Changing one does not change the others, which is why an export so often comes out white when the canvas is dark, or transparent when nobody asked for transparency.",[14,23,24,25,30],{},"This page is a focused recipe within ",[26,27,29],"a",{"href":28},"\u002Fpyqgis-cartography-visualization\u002Fmap-canvas-and-image-export\u002F","Map Canvas Control and Image Export in PyQGIS",". It covers setting the colour on the canvas, on a render job, producing a transparent PNG for compositing, and storing the choice so it survives a project reload.",[14,32,33],{},[34,35,40,44,48,55,72,81,91,97,103,112,118,122,127,131,134,137,140,143,146,149,152,156,159,163,166,169,173,179,181],"svg",{"viewBox":36,"role":37,"ariaLabel":38,"xmlns":39},"0 0 760 248","img","Three independent places the background colour is stored: the canvas widget, a render job's map settings, and the project file, each affecting a different output","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg",[41,42,43],"title",{},"Three places the background colour lives",[45,46,47],"desc",{},"The canvas widget's background affects only what is on screen and is lost on reload. A render job's map settings background affects only the exported image and defaults to transparent when the settings are built from scratch. The project's stored background is what a reopened project uses and is what a new canvas inherits.",[49,50],"rect",{"x":51,"y":51,"width":52,"height":53,"fill":54},"0","760","248","#f6f3ea",[56,57,58],"defs",{},[59,60,67],"marker",{"id":61,"viewBox":62,"refX":63,"refY":64,"markerWidth":65,"markerHeight":65,"orient":66},"bgPlaceArrow","0 0 10 10","8","5","7","auto-start-reverse",[68,69],"path",{"d":70,"fill":71},"M0 0 L10 5 L0 10 z","#0f766e",[73,74,80],"text",{"x":75,"y":76,"style":77,"fill":78,"textAnchor":79},"380","26","text-anchor:middle;font-size:14px;font-weight:bold;font-family:sans-serif","#17211d","middle","Setting one of these does not set the other two",[49,82],{"x":83,"y":84,"width":85,"height":86,"rx":87,"fill":88,"stroke":89,"style":90},"16","52","228","164","10","#fffdf7","#2563eb","stroke-width:2.5",[73,92,96],{"x":93,"y":94,"style":95,"fill":89,"textAnchor":79},"130","78","text-anchor:middle;font-size:12px;font-weight:bold;font-family:sans-serif","canvas widget",[73,98,102],{"x":93,"y":99,"style":100,"fill":101,"textAnchor":79},"102","text-anchor:middle;font-size:10.5px;font-family:monospace","#2f3b35","canvas.setCanvasColor()",[49,104],{"x":84,"y":105,"width":106,"height":107,"rx":108,"fill":109,"stroke":110,"style":111},"120","156","48","4","#26322d","#59645f","stroke-width:1.5",[73,113,117],{"x":93,"y":114,"style":115,"fill":116,"textAnchor":79},"149","text-anchor:middle;font-size:11px;font-family:sans-serif","#d9f99d","what you see",[73,119,121],{"x":93,"y":120,"style":115,"fill":101,"textAnchor":79},"190","on screen only",[73,123,126],{"x":93,"y":124,"style":115,"fill":125,"textAnchor":79},"208","#b45309","lost on reload",[49,128],{"x":129,"y":84,"width":85,"height":86,"rx":87,"fill":88,"stroke":130,"style":90},"266","#15803d",[73,132,133],{"x":75,"y":94,"style":95,"fill":130,"textAnchor":79},"map settings",[73,135,136],{"x":75,"y":99,"style":100,"fill":101,"textAnchor":79},"setBackgroundColor()",[49,138],{"x":139,"y":105,"width":106,"height":107,"rx":108,"fill":88,"stroke":110,"style":111},"302",[73,141,142],{"x":75,"y":114,"style":115,"fill":101,"textAnchor":79},"the exported PNG",[73,144,145],{"x":75,"y":120,"style":115,"fill":101,"textAnchor":79},"render jobs only",[73,147,148],{"x":75,"y":124,"style":115,"fill":125,"textAnchor":79},"transparent by default",[49,150],{"x":151,"y":84,"width":85,"height":86,"rx":87,"fill":88,"stroke":125,"style":90},"516",[73,153,155],{"x":154,"y":94,"style":95,"fill":125,"textAnchor":79},"630","project",[73,157,158],{"x":154,"y":99,"style":100,"fill":101,"textAnchor":79},"writeEntry(\"Gui\", …)",[49,160],{"x":161,"y":105,"width":106,"height":107,"rx":108,"fill":162,"stroke":110,"style":111},"552","#e7e2d4",[73,164,165],{"x":154,"y":114,"style":115,"fill":101,"textAnchor":79},"the reopened project",[73,167,168],{"x":154,"y":120,"style":115,"fill":101,"textAnchor":79},"persists in the .qgz",[73,170,172],{"x":154,"y":124,"style":171,"fill":130,"textAnchor":79},"text-anchor:middle;font-size:11px;font-weight:bold;font-family:sans-serif","what a new canvas inherits",[174,175],"line",{"x1":154,"y1":176,"x2":154,"y2":177,"stroke":71,"style":178},"216","232","stroke-width:2",[174,180],{"x1":154,"y1":177,"x2":93,"y2":177,"stroke":71,"style":178},[174,182],{"x1":93,"y1":177,"x2":93,"y2":183,"stroke":71,"style":184},"220","stroke-width:2;marker-end:url(#bgPlaceArrow)",[186,187,189],"h2",{"id":188},"prerequisites","Prerequisites",[191,192,193,201,208],"ul",{},[194,195,196,200],"li",{},[197,198,199],"strong",{},"QGIS 3.34 LTR"," (bundled Python 3.12) or newer.",[194,202,203,204,207],{},"For the canvas sections, QGIS Desktop with ",[18,205,206],{},"iface"," available.",[194,209,210,211,215],{},"For the export sections, no GUI is required — see ",[26,212,214],{"href":213},"\u002Fpyqgis-cartography-visualization\u002Fmap-canvas-and-image-export\u002Frender-layer-to-image-without-gui-pyqgis\u002F","Render a Layer to an Image Headless in PyQGIS",".",[186,217,219],{"id":218},"set-it-on-the-canvas","Set it on the canvas",[14,221,222],{},"One call, and the canvas repaints itself.",[224,225,230],"pre",{"className":226,"code":227,"language":228,"meta":229,"style":229},"language-python shiki shiki-themes github-dark","from qgis.PyQt.QtGui import QColor\n\ncanvas = iface.mapCanvas()\ncanvas.setCanvasColor(QColor(\"#0f1a17\"))\ncanvas.refresh()\n\nprint(canvas.canvasColor().name())\n","python","",[18,231,232,250,257,269,282,288,293],{"__ignoreMap":229},[233,234,236,240,244,247],"span",{"class":174,"line":235},1,[233,237,239],{"class":238},"snl16","from",[233,241,243],{"class":242},"s95oV"," qgis.PyQt.QtGui ",[233,245,246],{"class":238},"import",[233,248,249],{"class":242}," QColor\n",[233,251,253],{"class":174,"line":252},2,[233,254,256],{"emptyLinePlaceholder":255},true,"\n",[233,258,260,263,266],{"class":174,"line":259},3,[233,261,262],{"class":242},"canvas ",[233,264,265],{"class":238},"=",[233,267,268],{"class":242}," iface.mapCanvas()\n",[233,270,272,275,279],{"class":174,"line":271},4,[233,273,274],{"class":242},"canvas.setCanvasColor(QColor(",[233,276,278],{"class":277},"sU2Wk","\"#0f1a17\"",[233,280,281],{"class":242},"))\n",[233,283,285],{"class":174,"line":284},5,[233,286,287],{"class":242},"canvas.refresh()\n",[233,289,291],{"class":174,"line":290},6,[233,292,256],{"emptyLinePlaceholder":255},[233,294,296,300],{"class":174,"line":295},7,[233,297,299],{"class":298},"sDLfK","print",[233,301,302],{"class":242},"(canvas.canvasColor().name())\n",[14,304,305,308,309,312,313,316,317,320,321,324,325,328],{},[197,306,307],{},"Breakdown:"," ",[18,310,311],{},"QColor"," accepts a hex string, an ",[18,314,315],{},"(r, g, b)"," triple, or a named colour such as ",[18,318,319],{},"\"white\"",". ",[18,322,323],{},"setCanvasColor()"," changes only the widget — nothing is written to the project, so the colour is gone the next time the project is opened. ",[18,326,327],{},"canvasColor().name()"," returns the hex form, which is the easiest way to read the current value back.",[14,330,331],{},"This is the right call for a plugin that offers a dark-map mode or flips the background temporarily while something is being previewed. It is the wrong call for anything that needs to persist.",[186,333,335],{"id":334},"set-it-on-a-render-job","Set it on a render job",[14,337,338,339,341,342,345],{},"A ",[18,340,20],{}," built from scratch has a ",[197,343,344],{},"transparent"," background. That is a sensible default for compositing and a surprising one when the image lands in a report.",[224,347,349],{"className":226,"code":348,"language":228,"meta":229,"style":229},"from qgis.core import QgsMapSettings, QgsMapRendererParallelJob, QgsProject\nfrom qgis.PyQt.QtCore import QSize\nfrom qgis.PyQt.QtGui import QColor\n\nlayer = QgsProject.instance().mapLayersByName(\"parcels\")[0]\n\nsettings = QgsMapSettings()\nsettings.setLayers([layer])\nsettings.setDestinationCrs(layer.crs())\nsettings.setOutputSize(QSize(1200, 900))\nsettings.setBackgroundColor(QColor(\"#ffffff\"))\n\nextent = layer.extent()\nextent.scale(1.1)\nsettings.setExtent(extent)\n\njob = QgsMapRendererParallelJob(settings)\njob.start()\njob.waitForFinished()\njob.renderedImage().save(\"\u002Fdata\u002Fexports\u002Fparcels.png\", \"png\")\n",[18,350,351,363,375,385,389,410,414,424,430,436,453,464,469,480,492,498,503,514,520,526],{"__ignoreMap":229},[233,352,353,355,358,360],{"class":174,"line":235},[233,354,239],{"class":238},[233,356,357],{"class":242}," qgis.core ",[233,359,246],{"class":238},[233,361,362],{"class":242}," QgsMapSettings, QgsMapRendererParallelJob, QgsProject\n",[233,364,365,367,370,372],{"class":174,"line":252},[233,366,239],{"class":238},[233,368,369],{"class":242}," qgis.PyQt.QtCore ",[233,371,246],{"class":238},[233,373,374],{"class":242}," QSize\n",[233,376,377,379,381,383],{"class":174,"line":259},[233,378,239],{"class":238},[233,380,243],{"class":242},[233,382,246],{"class":238},[233,384,249],{"class":242},[233,386,387],{"class":174,"line":271},[233,388,256],{"emptyLinePlaceholder":255},[233,390,391,394,396,399,402,405,407],{"class":174,"line":284},[233,392,393],{"class":242},"layer ",[233,395,265],{"class":238},[233,397,398],{"class":242}," QgsProject.instance().mapLayersByName(",[233,400,401],{"class":277},"\"parcels\"",[233,403,404],{"class":242},")[",[233,406,51],{"class":298},[233,408,409],{"class":242},"]\n",[233,411,412],{"class":174,"line":290},[233,413,256],{"emptyLinePlaceholder":255},[233,415,416,419,421],{"class":174,"line":295},[233,417,418],{"class":242},"settings ",[233,420,265],{"class":238},[233,422,423],{"class":242}," QgsMapSettings()\n",[233,425,427],{"class":174,"line":426},8,[233,428,429],{"class":242},"settings.setLayers([layer])\n",[233,431,433],{"class":174,"line":432},9,[233,434,435],{"class":242},"settings.setDestinationCrs(layer.crs())\n",[233,437,439,442,445,448,451],{"class":174,"line":438},10,[233,440,441],{"class":242},"settings.setOutputSize(QSize(",[233,443,444],{"class":298},"1200",[233,446,447],{"class":242},", ",[233,449,450],{"class":298},"900",[233,452,281],{"class":242},[233,454,456,459,462],{"class":174,"line":455},11,[233,457,458],{"class":242},"settings.setBackgroundColor(QColor(",[233,460,461],{"class":277},"\"#ffffff\"",[233,463,281],{"class":242},[233,465,467],{"class":174,"line":466},12,[233,468,256],{"emptyLinePlaceholder":255},[233,470,472,475,477],{"class":174,"line":471},13,[233,473,474],{"class":242},"extent ",[233,476,265],{"class":238},[233,478,479],{"class":242}," layer.extent()\n",[233,481,483,486,489],{"class":174,"line":482},14,[233,484,485],{"class":242},"extent.scale(",[233,487,488],{"class":298},"1.1",[233,490,491],{"class":242},")\n",[233,493,495],{"class":174,"line":494},15,[233,496,497],{"class":242},"settings.setExtent(extent)\n",[233,499,501],{"class":174,"line":500},16,[233,502,256],{"emptyLinePlaceholder":255},[233,504,506,509,511],{"class":174,"line":505},17,[233,507,508],{"class":242},"job ",[233,510,265],{"class":238},[233,512,513],{"class":242}," QgsMapRendererParallelJob(settings)\n",[233,515,517],{"class":174,"line":516},18,[233,518,519],{"class":242},"job.start()\n",[233,521,523],{"class":174,"line":522},19,[233,524,525],{"class":242},"job.waitForFinished()\n",[233,527,529,532,535,537,540],{"class":174,"line":528},20,[233,530,531],{"class":242},"job.renderedImage().save(",[233,533,534],{"class":277},"\"\u002Fdata\u002Fexports\u002Fparcels.png\"",[233,536,447],{"class":242},[233,538,539],{"class":277},"\"png\"",[233,541,491],{"class":242},[14,543,544,308,546,548,549,552],{},[197,545,307],{},[18,547,136],{}," on the settings object is what the render job actually uses; the canvas colour has no influence on it. Setting it explicitly even when you want white is worth the line, because it documents the intent and removes any dependence on defaults. Copy-constructing the settings from ",[18,550,551],{},"canvas.mapSettings()"," instead would inherit the canvas colour, which is the shortcut when you want the export to match the screen.",[186,554,556],{"id":555},"produce-a-transparent-png","Produce a transparent PNG",[14,558,559],{},"For a map that will be composited into a layout, a web page or a report template, transparency is the point.",[224,561,563],{"className":226,"code":562,"language":228,"meta":229,"style":229},"from qgis.PyQt.QtCore import Qt\nfrom qgis.PyQt.QtGui import QColor\n\nsettings.setBackgroundColor(QColor(Qt.transparent))\n\njob = QgsMapRendererParallelJob(settings)\njob.start()\njob.waitForFinished()\n\nimage = job.renderedImage()\nprint(\"has alpha:\", image.hasAlphaChannel())\nimage.save(\"\u002Fdata\u002Fexports\u002Fparcels_transparent.png\", \"png\")\n",[18,564,565,576,586,590,595,599,607,611,615,619,629,642],{"__ignoreMap":229},[233,566,567,569,571,573],{"class":174,"line":235},[233,568,239],{"class":238},[233,570,369],{"class":242},[233,572,246],{"class":238},[233,574,575],{"class":242}," Qt\n",[233,577,578,580,582,584],{"class":174,"line":252},[233,579,239],{"class":238},[233,581,243],{"class":242},[233,583,246],{"class":238},[233,585,249],{"class":242},[233,587,588],{"class":174,"line":259},[233,589,256],{"emptyLinePlaceholder":255},[233,591,592],{"class":174,"line":271},[233,593,594],{"class":242},"settings.setBackgroundColor(QColor(Qt.transparent))\n",[233,596,597],{"class":174,"line":284},[233,598,256],{"emptyLinePlaceholder":255},[233,600,601,603,605],{"class":174,"line":290},[233,602,508],{"class":242},[233,604,265],{"class":238},[233,606,513],{"class":242},[233,608,609],{"class":174,"line":295},[233,610,519],{"class":242},[233,612,613],{"class":174,"line":426},[233,614,525],{"class":242},[233,616,617],{"class":174,"line":432},[233,618,256],{"emptyLinePlaceholder":255},[233,620,621,624,626],{"class":174,"line":438},[233,622,623],{"class":242},"image ",[233,625,265],{"class":238},[233,627,628],{"class":242}," job.renderedImage()\n",[233,630,631,633,636,639],{"class":174,"line":455},[233,632,299],{"class":298},[233,634,635],{"class":242},"(",[233,637,638],{"class":277},"\"has alpha:\"",[233,640,641],{"class":242},", image.hasAlphaChannel())\n",[233,643,644,647,650,652,654],{"class":174,"line":466},[233,645,646],{"class":242},"image.save(",[233,648,649],{"class":277},"\"\u002Fdata\u002Fexports\u002Fparcels_transparent.png\"",[233,651,447],{"class":242},[233,653,539],{"class":277},[233,655,491],{"class":242},[14,657,658,308,660,663,664,667,668,671],{},[197,659,307],{},[18,661,662],{},"QColor(Qt.transparent)"," is fully transparent black, which is the correct value — a colour with zero alpha rather than a colour that merely looks like the page. ",[18,665,666],{},"hasAlphaChannel()"," confirms the rendered image can actually carry transparency; a format such as JPEG cannot, so saving a transparent render as ",[18,669,670],{},".jpg"," silently composites it onto black. Always save transparent output as PNG.",[14,673,674],{},[34,675,678,681,684,687,690,718,738,805],{"viewBox":676,"role":37,"ariaLabel":677,"xmlns":39},"0 0 760 240","The same map rendered on a white background, a dark background and a transparent background shown over a checkerboard, with a note that JPEG cannot carry transparency",[41,679,680],{},"Three background choices for the same map",[45,682,683],{},"The same parcel polygons are rendered three times. On a white background the map reads as a printed figure. On a dark background it reads as a screen dashboard. On a transparent background, shown over a checkerboard, only the polygons remain, ready to composite. A note warns that saving transparent output as JPEG flattens it onto black.",[49,685],{"x":51,"y":51,"width":52,"height":686,"fill":54},"240",[73,688,689],{"x":75,"y":76,"style":77,"fill":78,"textAnchor":79},"Same render, three backgrounds",[691,692,693,697,702,707,711,714],"g",{},[49,694],{"x":83,"y":695,"width":85,"height":696,"rx":87,"fill":88,"stroke":110,"style":178},"44","150",[73,698,701],{"x":93,"y":699,"style":700,"fill":78,"textAnchor":79},"68","text-anchor:middle;font-size:11.5px;font-weight:bold;font-family:sans-serif","#ffffff",[49,703],{"x":695,"y":704,"width":705,"height":706,"fill":88,"stroke":110,"style":111},"82","172","96",[68,708],{"d":709,"fill":71,"fillOpacity":710,"stroke":71,"style":178},"M62 164 L62 106 L118 100 L142 134 L110 168 Z",0.3,[68,712],{"d":713,"fill":125,"fillOpacity":710,"stroke":125,"style":178},"M148 168 L146 118 L200 112 L204 164 Z",[73,715,717],{"x":93,"y":716,"style":115,"fill":101,"textAnchor":79},"212","a printed figure",[691,719,720,722,725,728,732,735],{},[49,721],{"x":129,"y":695,"width":85,"height":696,"rx":87,"fill":88,"stroke":110,"style":178},[73,723,724],{"x":75,"y":699,"style":700,"fill":78,"textAnchor":79},"#0f1a17",[49,726],{"x":727,"y":704,"width":705,"height":706,"fill":109,"stroke":110,"style":111},"294",[68,729],{"d":730,"fill":71,"fillOpacity":731,"stroke":71,"style":178},"M312 164 L312 106 L368 100 L392 134 L360 168 Z",0.55,[68,733],{"d":734,"fill":125,"fillOpacity":731,"stroke":125,"style":178},"M398 168 L396 118 L450 112 L454 164 Z",[73,736,737],{"x":75,"y":716,"style":115,"fill":101,"textAnchor":79},"a screen dashboard",[691,739,740,742,745,792,795,799,802],{},[49,741],{"x":151,"y":695,"width":85,"height":696,"rx":87,"fill":88,"stroke":130,"style":90},[73,743,744],{"x":154,"y":699,"style":700,"fill":130,"textAnchor":79},"Qt.transparent",[691,746,747,750,754,757,759,762,766,769,772,775,777,779,781,783,786,788,790],{},[49,748],{"x":749,"y":704,"width":705,"height":706,"fill":162},"544",[49,751],{"x":749,"y":704,"width":752,"height":753,"fill":88},"21.5","24",[49,755],{"x":756,"y":704,"width":752,"height":753,"fill":88},"587",[49,758],{"x":154,"y":704,"width":752,"height":753,"fill":88},[49,760],{"x":761,"y":704,"width":752,"height":753,"fill":88},"673",[49,763],{"x":764,"y":765,"width":752,"height":753,"fill":88},"565.5","106",[49,767],{"x":768,"y":765,"width":752,"height":753,"fill":88},"608.5",[49,770],{"x":771,"y":765,"width":752,"height":753,"fill":88},"651.5",[49,773],{"x":774,"y":765,"width":752,"height":753,"fill":88},"694.5",[49,776],{"x":749,"y":93,"width":752,"height":753,"fill":88},[49,778],{"x":756,"y":93,"width":752,"height":753,"fill":88},[49,780],{"x":154,"y":93,"width":752,"height":753,"fill":88},[49,782],{"x":761,"y":93,"width":752,"height":753,"fill":88},[49,784],{"x":764,"y":785,"width":752,"height":753,"fill":88},"154",[49,787],{"x":768,"y":785,"width":752,"height":753,"fill":88},[49,789],{"x":771,"y":785,"width":752,"height":753,"fill":88},[49,791],{"x":774,"y":785,"width":752,"height":753,"fill":88},[49,793],{"x":749,"y":704,"width":705,"height":706,"fill":794,"stroke":110,"style":111},"none",[68,796],{"d":797,"fill":71,"fillOpacity":798,"stroke":71,"style":178},"M562 164 L562 106 L618 100 L642 134 L610 168 Z",0.4,[68,800],{"d":801,"fill":125,"fillOpacity":798,"stroke":125,"style":178},"M648 168 L646 118 L700 112 L704 164 Z",[73,803,804],{"x":154,"y":716,"style":115,"fill":130,"textAnchor":79},"ready to composite — save as PNG",[73,806,807],{"x":75,"y":177,"style":115,"fill":110,"textAnchor":79},"saving a transparent render as JPEG flattens it onto black",[186,809,811],{"id":810},"make-it-persist-in-the-project","Make it persist in the project",[14,813,814],{},"To have the colour survive a reload, write it into the project's settings — which is where QGIS itself stores the value from Project Properties.",[224,816,818],{"className":226,"code":817,"language":228,"meta":229,"style":229},"from qgis.core import QgsProject\nfrom qgis.PyQt.QtGui import QColor\n\ncolour = QColor(\"#0f1a17\")\nproject = QgsProject.instance()\n\nproject.writeEntry(\"Gui\", \"\u002FCanvasColorRedPart\", colour.red())\nproject.writeEntry(\"Gui\", \"\u002FCanvasColorGreenPart\", colour.green())\nproject.writeEntry(\"Gui\", \"\u002FCanvasColorBluePart\", colour.blue())\n\niface.mapCanvas().setCanvasColor(colour)\niface.mapCanvas().refresh()\nproject.write()\n",[18,819,820,831,841,845,859,869,873,889,903,917,921,926,931],{"__ignoreMap":229},[233,821,822,824,826,828],{"class":174,"line":235},[233,823,239],{"class":238},[233,825,357],{"class":242},[233,827,246],{"class":238},[233,829,830],{"class":242}," QgsProject\n",[233,832,833,835,837,839],{"class":174,"line":252},[233,834,239],{"class":238},[233,836,243],{"class":242},[233,838,246],{"class":238},[233,840,249],{"class":242},[233,842,843],{"class":174,"line":259},[233,844,256],{"emptyLinePlaceholder":255},[233,846,847,850,852,855,857],{"class":174,"line":271},[233,848,849],{"class":242},"colour ",[233,851,265],{"class":238},[233,853,854],{"class":242}," QColor(",[233,856,278],{"class":277},[233,858,491],{"class":242},[233,860,861,864,866],{"class":174,"line":284},[233,862,863],{"class":242},"project ",[233,865,265],{"class":238},[233,867,868],{"class":242}," QgsProject.instance()\n",[233,870,871],{"class":174,"line":290},[233,872,256],{"emptyLinePlaceholder":255},[233,874,875,878,881,883,886],{"class":174,"line":295},[233,876,877],{"class":242},"project.writeEntry(",[233,879,880],{"class":277},"\"Gui\"",[233,882,447],{"class":242},[233,884,885],{"class":277},"\"\u002FCanvasColorRedPart\"",[233,887,888],{"class":242},", colour.red())\n",[233,890,891,893,895,897,900],{"class":174,"line":426},[233,892,877],{"class":242},[233,894,880],{"class":277},[233,896,447],{"class":242},[233,898,899],{"class":277},"\"\u002FCanvasColorGreenPart\"",[233,901,902],{"class":242},", colour.green())\n",[233,904,905,907,909,911,914],{"class":174,"line":432},[233,906,877],{"class":242},[233,908,880],{"class":277},[233,910,447],{"class":242},[233,912,913],{"class":277},"\"\u002FCanvasColorBluePart\"",[233,915,916],{"class":242},", colour.blue())\n",[233,918,919],{"class":174,"line":438},[233,920,256],{"emptyLinePlaceholder":255},[233,922,923],{"class":174,"line":455},[233,924,925],{"class":242},"iface.mapCanvas().setCanvasColor(colour)\n",[233,927,928],{"class":174,"line":466},[233,929,930],{"class":242},"iface.mapCanvas().refresh()\n",[233,932,933],{"class":174,"line":471},[233,934,935],{"class":242},"project.write()\n",[14,937,938,940,941,944,945,948,949,952,953,956],{},[197,939,307],{}," QGIS stores the canvas colour as three separate integer entries under the ",[18,942,943],{},"Gui"," scope rather than as a single hex string, which is why three calls are needed. ",[18,946,947],{},"writeEntry()"," only stages the change in memory; ",[18,950,951],{},"project.write()"," is what saves the ",[18,954,955],{},".qgz"," file. Setting the canvas colour as well means the change is visible immediately rather than only after the next reload — writing the entries alone updates the file but not the current view, which looks like the call did nothing.",[186,958,960],{"id":959},"keep-the-layers-readable-against-the-background","Keep the layers readable against the background",[14,962,963],{},"Darkening the canvas is only half a dark map. Layer styling was designed against whatever background it was authored on, and moving it to the opposite end of the scale can leave dark linework invisible and light labels lost. A background change that is not accompanied by a styling review produces a map that looks striking in a screenshot and is unusable in practice.",[14,965,966],{},[34,967,970,973,976,979,982,1016,1040],{"viewBox":968,"role":37,"ariaLabel":969,"xmlns":39},"0 0 760 258","The same layer styling shown on a light and a dark background, where dark linework and dark label text disappear against the dark canvas until they are re-coloured",[41,971,972],{},"Styling that only works on one background",[45,974,975],{},"Three panels. On a light background, dark roads and dark labels read clearly. On a dark background with the same styling, the roads and labels nearly vanish. In the third panel the same dark background is paired with lightened linework and label text, and the map is readable again.",[49,977],{"x":51,"y":51,"width":52,"height":978,"fill":54},"258",[73,980,981],{"x":75,"y":76,"style":77,"fill":78,"textAnchor":79},"Changing the background is a styling change, not a setting",[691,983,984,990,994,1000,1003,1007,1012],{},[49,985],{"x":986,"y":987,"width":988,"height":989,"rx":87,"fill":88,"stroke":130,"style":90},"12","46","236","196",[73,991,993],{"x":93,"y":992,"style":700,"fill":130,"textAnchor":79},"70","light bg · dark ink",[49,995],{"x":996,"y":997,"width":998,"height":999,"fill":88,"stroke":110,"style":111},"36","84","188","118",[68,1001],{"d":1002,"fill":794,"stroke":101,"style":90},"M36 176 L88 128 L148 152 L224 104",[68,1004],{"d":1005,"fill":794,"stroke":101,"style":1006},"M60 96 L60 202","stroke-width:1.6",[73,1008,1011],{"x":1009,"y":105,"style":1010,"fill":101},"98","font-size:10.5px;font-family:sans-serif","Ash Road",[73,1013,1015],{"x":93,"y":1014,"style":115,"fill":130,"textAnchor":79},"224","readable",[691,1017,1018,1022,1025,1028,1031,1034,1037],{},[49,1019],{"x":1020,"y":987,"width":988,"height":989,"rx":87,"fill":88,"stroke":1021,"style":90},"262","#b91c1c",[73,1023,1024],{"x":75,"y":992,"style":700,"fill":1021,"textAnchor":79},"dark bg · same ink",[49,1026],{"x":1027,"y":997,"width":998,"height":999,"fill":109,"stroke":110,"style":111},"286",[68,1029],{"d":1030,"fill":794,"stroke":101,"style":90},"M286 176 L338 128 L398 152 L474 104",[68,1032],{"d":1033,"fill":794,"stroke":101,"style":1006},"M310 96 L310 202",[73,1035,1011],{"x":1036,"y":105,"style":1010,"fill":101},"348",[73,1038,1039],{"x":75,"y":1014,"style":115,"fill":1021,"textAnchor":79},"linework and labels vanish",[691,1041,1042,1045,1048,1051,1054,1058,1061],{},[49,1043],{"x":1044,"y":987,"width":988,"height":989,"rx":87,"fill":88,"stroke":130,"style":90},"512",[73,1046,1047],{"x":154,"y":992,"style":700,"fill":130,"textAnchor":79},"dark bg · light ink",[49,1049],{"x":1050,"y":997,"width":998,"height":999,"fill":109,"stroke":110,"style":111},"536",[68,1052],{"d":1053,"fill":794,"stroke":162,"style":90},"M536 176 L588 128 L648 152 L724 104",[68,1055],{"d":1056,"fill":794,"stroke":1057,"style":1006},"M560 96 L560 202","#a7b1ab",[73,1059,1011],{"x":1060,"y":105,"style":1010,"fill":162},"598",[73,1062,1063],{"x":154,"y":1014,"style":115,"fill":130,"textAnchor":79},"readable again",[14,1065,1066],{},"The practical approach is to keep two saved styles per layer and swap them alongside the background, rather than trying to recolour everything in code:",[224,1068,1070],{"className":226,"code":1069,"language":228,"meta":229,"style":229},"from qgis.PyQt.QtGui import QColor\n\nDARK = {\"bg\": \"#0f1a17\", \"style\": \"\u002Fdata\u002Fstyles\u002Fparcels_dark.qml\"}\nLIGHT = {\"bg\": \"#f6f3ea\", \"style\": \"\u002Fdata\u002Fstyles\u002Fparcels_light.qml\"}\n\n\ndef apply_theme(canvas, layers, theme):\n    canvas.setCanvasColor(QColor(theme[\"bg\"]))\n    for layer in layers:\n        layer.loadNamedStyle(theme[\"style\"])\n        layer.triggerRepaint()\n    canvas.refresh()\n",[18,1071,1072,1082,1086,1118,1145,1149,1153,1165,1175,1189,1199,1204],{"__ignoreMap":229},[233,1073,1074,1076,1078,1080],{"class":174,"line":235},[233,1075,239],{"class":238},[233,1077,243],{"class":242},[233,1079,246],{"class":238},[233,1081,249],{"class":242},[233,1083,1084],{"class":174,"line":252},[233,1085,256],{"emptyLinePlaceholder":255},[233,1087,1088,1091,1094,1097,1100,1103,1105,1107,1110,1112,1115],{"class":174,"line":259},[233,1089,1090],{"class":298},"DARK",[233,1092,1093],{"class":238}," =",[233,1095,1096],{"class":242}," {",[233,1098,1099],{"class":277},"\"bg\"",[233,1101,1102],{"class":242},": ",[233,1104,278],{"class":277},[233,1106,447],{"class":242},[233,1108,1109],{"class":277},"\"style\"",[233,1111,1102],{"class":242},[233,1113,1114],{"class":277},"\"\u002Fdata\u002Fstyles\u002Fparcels_dark.qml\"",[233,1116,1117],{"class":242},"}\n",[233,1119,1120,1123,1125,1127,1129,1131,1134,1136,1138,1140,1143],{"class":174,"line":271},[233,1121,1122],{"class":298},"LIGHT",[233,1124,1093],{"class":238},[233,1126,1096],{"class":242},[233,1128,1099],{"class":277},[233,1130,1102],{"class":242},[233,1132,1133],{"class":277},"\"#f6f3ea\"",[233,1135,447],{"class":242},[233,1137,1109],{"class":277},[233,1139,1102],{"class":242},[233,1141,1142],{"class":277},"\"\u002Fdata\u002Fstyles\u002Fparcels_light.qml\"",[233,1144,1117],{"class":242},[233,1146,1147],{"class":174,"line":284},[233,1148,256],{"emptyLinePlaceholder":255},[233,1150,1151],{"class":174,"line":290},[233,1152,256],{"emptyLinePlaceholder":255},[233,1154,1155,1158,1162],{"class":174,"line":295},[233,1156,1157],{"class":238},"def",[233,1159,1161],{"class":1160},"svObZ"," apply_theme",[233,1163,1164],{"class":242},"(canvas, layers, theme):\n",[233,1166,1167,1170,1172],{"class":174,"line":426},[233,1168,1169],{"class":242},"    canvas.setCanvasColor(QColor(theme[",[233,1171,1099],{"class":277},[233,1173,1174],{"class":242},"]))\n",[233,1176,1177,1180,1183,1186],{"class":174,"line":432},[233,1178,1179],{"class":238},"    for",[233,1181,1182],{"class":242}," layer ",[233,1184,1185],{"class":238},"in",[233,1187,1188],{"class":242}," layers:\n",[233,1190,1191,1194,1196],{"class":174,"line":438},[233,1192,1193],{"class":242},"        layer.loadNamedStyle(theme[",[233,1195,1109],{"class":277},[233,1197,1198],{"class":242},"])\n",[233,1200,1201],{"class":174,"line":455},[233,1202,1203],{"class":242},"        layer.triggerRepaint()\n",[233,1205,1206],{"class":174,"line":466},[233,1207,1208],{"class":242},"    canvas.refresh()\n",[14,1210,1211,308,1213,1216,1217,1220,1221,1224,1225,1228],{},[197,1212,307],{},[18,1214,1215],{},"loadNamedStyle()"," replaces the layer's whole renderer and labelling configuration from a ",[18,1218,1219],{},".qml"," file, so a designer can build both variants in the GUI and the script simply picks one. Keeping the background and the style path together in a dictionary means the two can never drift apart — the failure this prevents is exactly a dark background applied without the matching styling. ",[18,1222,1223],{},"triggerRepaint()"," per layer plus one ",[18,1226,1227],{},"refresh()"," on the canvas is the minimum needed to make the swap visible.",[186,1230,1232],{"id":1231},"qgis-version-compatibility","QGIS version compatibility",[14,1234,1235,1236,1238],{},"The examples target ",[197,1237,199],{}," (Python 3.12).",[1240,1241,1242,1258],"table",{},[1243,1244,1245],"thead",{},[1246,1247,1248,1252,1255],"tr",{},[1249,1250,1251],"th",{},"QGIS version",[1249,1253,1254],{},"Python",[1249,1256,1257],{},"Notes",[1259,1260,1261,1273,1284],"tbody",{},[1246,1262,1263,1267,1270],{},[1264,1265,1266],"td",{},"3.28 LTR",[1264,1268,1269],{},"3.9",[1264,1271,1272],{},"Identical API and project entry keys.",[1246,1274,1275,1278,1281],{},[1264,1276,1277],{},"3.34 LTR",[1264,1279,1280],{},"3.12",[1264,1282,1283],{},"Baseline for this page.",[1246,1285,1286,1289,1291],{},[1264,1287,1288],{},"3.40 \u002F 3.44",[1264,1290,1280],{},[1264,1292,1293,1294,1297,1298,1300],{},"Project background colour also exposed through ",[18,1295,1296],{},"QgsProject.backgroundColor()","; the ",[18,1299,943],{}," entries remain valid.",[14,1302,1303,447,1305,1307],{},[18,1304,323],{},[18,1306,136],{}," and the project entry keys are unchanged across 3.x.",[186,1309,1311],{"id":1310},"troubleshooting","Troubleshooting",[191,1313,1314,1326,1335,1341,1352,1358],{},[194,1315,1316,1319,1320,1322,1323,1325],{},[197,1317,1318],{},"The export is transparent when you wanted white."," A ",[18,1321,20],{}," built from scratch defaults to transparent. Call ",[18,1324,136],{}," explicitly.",[194,1327,1328,1331,1332,1334],{},[197,1329,1330],{},"The export is white when the canvas is dark."," The settings object does not inherit the canvas colour. Copy-construct from ",[18,1333,551],{}," or set the colour on both.",[194,1336,1337,1340],{},[197,1338,1339],{},"The transparent PNG has a black background."," It was saved as JPEG, which has no alpha channel. Save as PNG.",[194,1342,1343,1346,1347,1349,1350,215],{},[197,1344,1345],{},"The colour is lost when the project reopens."," Only the canvas widget was changed. Write the three ",[18,1348,943],{}," entries and call ",[18,1351,951],{},[194,1353,1354,1357],{},[197,1355,1356],{},"Writing the project entries changed nothing on screen."," They take effect on load. Set the canvas colour too for an immediate result.",[194,1359,1360,1363,1364,215],{},[197,1361,1362],{},"The background shows through the layers oddly."," A layer has partial opacity, so the background is compositing through it. Check ",[18,1365,1366],{},"layer.opacity()",[186,1368,1370],{"id":1369},"conclusion","Conclusion",[14,1372,1373,1374,1376,1377,1379],{},"The background colour lives in three independent places, and knowing which one you are setting removes the whole family of \"the export does not match the screen\" surprises. Set it on the canvas for the view, on ",[18,1375,20],{}," for every export — including explicitly when you want white — and in the project's ",[18,1378,943],{}," entries when the choice should persist.",[186,1381,1383],{"id":1382},"frequently-asked-questions","Frequently Asked Questions",[14,1385,1386,1389,1390,1392,1393,1396,1397,1399],{},[197,1387,1388],{},"Why is my exported image transparent when I did not ask for it?","\nA ",[18,1391,20],{}," constructed directly defaults to a transparent background. Call ",[18,1394,1395],{},"setBackgroundColor(QColor(\"#ffffff\"))",", or copy-construct the settings from ",[18,1398,551],{}," to inherit the project's colour.",[14,1401,1402,1405,1406,1409],{},[197,1403,1404],{},"How do I make a transparent PNG for compositing?","\nSet ",[18,1407,1408],{},"settings.setBackgroundColor(QColor(Qt.transparent))"," and save the rendered image as PNG. JPEG has no alpha channel, so a transparent render saved as JPEG is flattened onto black.",[14,1411,1412,1415,1417,1418,447,1421,1424,1425,1428,1429,1431,1432,215],{},[197,1413,1414],{},"Why does the canvas colour reset when I reopen the project?",[18,1416,323],{}," only changes the widget. Persist the choice by writing the ",[18,1419,1420],{},"CanvasColorRedPart",[18,1422,1423],{},"GreenPart"," and ",[18,1426,1427],{},"BluePart"," entries under the ",[18,1430,943],{}," scope and calling ",[18,1433,951],{},[14,1435,1436,1439],{},[197,1437,1438],{},"Does the canvas colour affect an export?","\nOnly if the render settings were copied from the canvas. A settings object built from scratch has its own background and ignores the canvas entirely.",[14,1441,1442,1445],{},[197,1443,1444],{},"Can I set a background image instead of a colour?","\nNot on the canvas itself — the background is a single colour. The equivalent is a raster or a plain-coloured polygon layer placed at the bottom of the draw order, which then renders like any other layer and appears in exports without any special handling.",[14,1447,1448,1451],{},[197,1449,1450],{},"Does the background colour affect printed layouts?","\nNo. A print layout has its own page background, set on the layout rather than the canvas. Changing the canvas colour has no effect on a PDF exported from a layout, which catches people out when a dark screen map prints on white paper.",[14,1453,1454,1457,1458,1460],{},[197,1455,1456],{},"Can different projects have different canvas colours?","\nYes — the colour is stored per project, so each ",[18,1459,955],{}," carries its own and switching projects switches the background.",[186,1462,1464],{"id":1463},"related","Related",[191,1466,1467,1472,1478,1482],{},[194,1468,1469,1471],{},[26,1470,29],{"href":28}," — the guide this recipe belongs to",[194,1473,1474],{},[26,1475,1477],{"href":1476},"\u002Fpyqgis-cartography-visualization\u002Fmap-canvas-and-image-export\u002Fexport-map-canvas-to-image-pyqgis\u002F","Export the Map Canvas to a PNG with PyQGIS",[194,1479,1480],{},[26,1481,214],{"href":213},[194,1483,1484],{},[26,1485,1487],{"href":1486},"\u002Fpyqgis-cartography-visualization\u002Fprogrammatic-layer-styling\u002F","Programmatic Layer Styling in PyQGIS",[1489,1490,1491],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}",{"title":229,"searchDepth":252,"depth":252,"links":1493},[1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504],{"id":188,"depth":252,"text":189},{"id":218,"depth":252,"text":219},{"id":334,"depth":252,"text":335},{"id":555,"depth":252,"text":556},{"id":810,"depth":252,"text":811},{"id":959,"depth":252,"text":960},{"id":1231,"depth":252,"text":1232},{"id":1310,"depth":252,"text":1311},{"id":1369,"depth":252,"text":1370},{"id":1382,"depth":252,"text":1383},{"id":1463,"depth":252,"text":1464},"Change the QGIS canvas background colour from Python, set it on a render job, produce transparent PNG exports, and store the choice in the project so it persists.","md",{"slug":1508,"type":1509,"breadcrumb":1510,"datePublished":1511,"dateModified":1511},"set-map-canvas-background-color-pyqgis","article","Canvas Background Colour","2026-08-01","\u002Fpyqgis-cartography-visualization\u002Fmap-canvas-and-image-export\u002Fset-map-canvas-background-color-pyqgis",{"title":5,"description":1505},"pyqgis-cartography-visualization\u002Fmap-canvas-and-image-export\u002Fset-map-canvas-background-color-pyqgis\u002Findex","5aWCyC-ef1awyArEOpnKkZ0J9EWRb9C1xqrkaz09xZ0",1785585990471]