[{"data":1,"prerenderedAt":1374},["ShallowReactive",2],{"doc:\u002Fpyqgis-cartography-visualization\u002Fprogrammatic-layer-styling\u002Fcopy-style-between-layers-pyqgis":3},{"id":4,"title":5,"body":6,"description":1363,"extension":1364,"meta":1365,"navigation":244,"path":1370,"seo":1371,"stem":1372,"__hash__":1373},"docs\u002Fpyqgis-cartography-visualization\u002Fprogrammatic-layer-styling\u002Fcopy-style-between-layers-pyqgis\u002Findex.md","Copy a Style Between Layers in PyQGIS",{"type":7,"value":8,"toc":1350},"minimark",[9,13,22,31,177,182,204,208,211,318,332,335,370,387,391,394,462,512,602,606,836,856,860,863,931,947,1041,1045,1048,1071,1116,1128,1132,1203,1210,1214,1263,1267,1273,1277,1283,1289,1299,1305,1311,1317,1321,1346],[10,11,5],"h1",{"id":12},"copy-a-style-between-layers-in-pyqgis",[14,15,16,17,21],"p",{},"A cartographer spends an afternoon getting one layer right, and then twelve more layers need the same treatment. Doing it by hand means twelve chances to end up with slightly different line widths; doing it from code takes two lines and guarantees they match. The subtlety is deciding ",[18,19,20],"em",{},"what"," to copy — symbology alone, or labelling, field aliases, forms and joins as well — and QGIS lets you choose.",[14,23,24,25,30],{},"This recipe belongs to ",[26,27,29],"a",{"href":28},"\u002Fpyqgis-cartography-visualization\u002Fprogrammatic-layer-styling\u002F","Programmatic Layer Styling",". It covers cloning a renderer, copying selected style categories, the style manager for layers that carry several styles, applying a saved style to many layers at once, and what happens when the target layer's fields do not match the source.",[14,32,33],{},[34,35,40,44,48,55,72,81,90,96,102,106,111,121,125,128,132,136,140,144,148,153,157,160,163,166,173],"svg",{"viewBox":36,"role":37,"ariaLabel":38,"xmlns":39},"0 0 760 278","img","Diagram of the style categories that can be copied between layers, including symbology, labelling, field aliases, forms, actions and joins","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg",[41,42,43],"title",{},"A style is more than symbology",[45,46,47],"desc",{},"Copying a style can include the renderer, the labelling, field aliases and widget configuration, layer actions, joins, the coordinate system, and layer metadata. Copying everything from a differently shaped layer brings across field configuration that does not apply, so the categories are selectable and copying only symbology and labelling is usually what is wanted.",[49,50],"rect",{"x":51,"y":51,"width":52,"height":53,"fill":54},"0","760","278","#f6f3ea",[56,57,58],"defs",{},[59,60,67],"marker",{"id":61,"viewBox":62,"refX":63,"refY":64,"markerWidth":65,"markerHeight":65,"orient":66},"styleArrow","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","28","text-anchor:middle;font-size:14px;font-weight:bold;font-family:sans-serif","#17211d","middle","Choose the categories, or bring across more than you meant",[49,82],{"x":83,"y":84,"width":85,"height":86,"rx":87,"fill":88,"stroke":71,"style":89},"20","60","180","160","10","#eef7f4","stroke-width:2.5",[73,91,95],{"x":92,"y":93,"style":94,"fill":71,"textAnchor":79},"110","88","text-anchor:middle;font-size:12px;font-weight:bold;font-family:sans-serif","source layer",[73,97,101],{"x":92,"y":98,"style":99,"fill":100,"textAnchor":79},"118","text-anchor:middle;font-size:11px;font-family:sans-serif","#2f3b35","styled by hand",[73,103,105],{"x":92,"y":104,"style":99,"fill":100,"textAnchor":79},"142","an afternoon's work",[73,107,110],{"x":92,"y":108,"style":99,"fill":109,"textAnchor":79},"172","#59645f","the one to copy from",[49,112],{"x":113,"y":114,"width":115,"height":116,"rx":117,"fill":118,"stroke":119,"style":120},"264","52","232","42","6","#fffdf7","#15803d","stroke-width:2",[73,122,124],{"x":75,"y":123,"style":99,"fill":100,"textAnchor":79},"78","symbology — nearly always",[49,126],{"x":113,"y":127,"width":115,"height":116,"rx":117,"fill":118,"stroke":119,"style":120},"100",[73,129,131],{"x":75,"y":130,"style":99,"fill":100,"textAnchor":79},"126","labelling — usually",[49,133],{"x":113,"y":134,"width":115,"height":116,"rx":117,"fill":118,"stroke":135,"style":120},"148","#b45309",[73,137,139],{"x":75,"y":138,"style":99,"fill":100,"textAnchor":79},"174","fields and forms — only if alike",[49,141],{"x":113,"y":142,"width":115,"height":116,"rx":117,"fill":118,"stroke":143,"style":120},"196","#b91c1c",[73,145,147],{"x":75,"y":146,"style":99,"fill":100,"textAnchor":79},"222","joins and actions — rarely",[49,149],{"x":150,"y":84,"width":85,"height":86,"rx":87,"fill":151,"stroke":152,"style":89},"560","#eff3ff","#2563eb",[73,154,156],{"x":155,"y":93,"style":94,"fill":152,"textAnchor":79},"650","target layers",[73,158,159],{"x":155,"y":98,"style":99,"fill":100,"textAnchor":79},"twelve of them",[73,161,162],{"x":155,"y":104,"style":99,"fill":100,"textAnchor":79},"identical result",[73,164,165],{"x":155,"y":108,"style":99,"fill":109,"textAnchor":79},"and no drifting line widths",[167,168],"line",{"x1":169,"y1":170,"x2":171,"y2":170,"stroke":71,"style":172},"200","140","258","stroke-width:2;marker-end:url(#styleArrow)",[167,174],{"x1":175,"y1":170,"x2":176,"y2":170,"stroke":71,"style":172},"496","554",[178,179,181],"h2",{"id":180},"prerequisites","Prerequisites",[183,184,185,193,196],"ul",{},[186,187,188,192],"li",{},[189,190,191],"strong",{},"QGIS 3.34 LTR"," (bundled Python 3.12) or newer.",[186,194,195],{},"Two or more layers of the same geometry type — a polygon renderer applied to a point layer does nothing useful.",[186,197,198,199,203],{},"A styled source layer; building one is covered in ",[26,200,202],{"href":201},"\u002Fpyqgis-cartography-visualization\u002Fprogrammatic-layer-styling\u002Fset-vector-layer-symbol-color-pyqgis\u002F","Set a Vector Layer Symbol Colour in PyQGIS",".",[178,205,207],{"id":206},"clone-the-renderer","Clone the renderer",[14,209,210],{},"The direct approach copies symbology and nothing else.",[212,213,218],"pre",{"className":214,"code":215,"language":216,"meta":217,"style":217},"language-python shiki shiki-themes github-dark","from qgis.core import QgsProject\n\nproject = QgsProject.instance()\nsource = project.mapLayersByName(\"Parcels 2025\")[0]\ntarget = project.mapLayersByName(\"Parcels 2026\")[0]\n\ntarget.setRenderer(source.renderer().clone())\ntarget.triggerRepaint()\n","python","",[219,220,221,239,246,258,282,301,306,312],"code",{"__ignoreMap":217},[222,223,225,229,233,236],"span",{"class":167,"line":224},1,[222,226,228],{"class":227},"snl16","from",[222,230,232],{"class":231},"s95oV"," qgis.core ",[222,234,235],{"class":227},"import",[222,237,238],{"class":231}," QgsProject\n",[222,240,242],{"class":167,"line":241},2,[222,243,245],{"emptyLinePlaceholder":244},true,"\n",[222,247,249,252,255],{"class":167,"line":248},3,[222,250,251],{"class":231},"project ",[222,253,254],{"class":227},"=",[222,256,257],{"class":231}," QgsProject.instance()\n",[222,259,261,264,266,269,273,276,279],{"class":167,"line":260},4,[222,262,263],{"class":231},"source ",[222,265,254],{"class":227},[222,267,268],{"class":231}," project.mapLayersByName(",[222,270,272],{"class":271},"sU2Wk","\"Parcels 2025\"",[222,274,275],{"class":231},")[",[222,277,51],{"class":278},"sDLfK",[222,280,281],{"class":231},"]\n",[222,283,285,288,290,292,295,297,299],{"class":167,"line":284},5,[222,286,287],{"class":231},"target ",[222,289,254],{"class":227},[222,291,268],{"class":231},[222,293,294],{"class":271},"\"Parcels 2026\"",[222,296,275],{"class":231},[222,298,51],{"class":278},[222,300,281],{"class":231},[222,302,304],{"class":167,"line":303},6,[222,305,245],{"emptyLinePlaceholder":244},[222,307,309],{"class":167,"line":308},7,[222,310,311],{"class":231},"target.setRenderer(source.renderer().clone())\n",[222,313,315],{"class":167,"line":314},8,[222,316,317],{"class":231},"target.triggerRepaint()\n",[14,319,320,323,324,327,328,331],{},[189,321,322],{},"Breakdown:"," ",[219,325,326],{},"clone()"," is essential — assigning ",[219,329,330],{},"source.renderer()"," directly would give both layers the same renderer object, so a later change to one silently changes the other, and destroying one layer leaves the other holding freed memory. The clone is independent from the moment it is made. This copies the whole symbology including categories, rules, colour ramps and data-defined overrides, which is exactly what you want when the target has the same fields. When it does not, the categories still copy but match nothing, which is where the field question below comes in.",[14,333,334],{},"Labelling is a separate object and needs its own line:",[212,336,338],{"className":214,"code":337,"language":216,"meta":217,"style":217},"if source.labeling() is not None:\n    target.setLabeling(source.labeling().clone())\n    target.setLabelsEnabled(source.labelsEnabled())\n",[219,339,340,360,365],{"__ignoreMap":217},[222,341,342,345,348,351,354,357],{"class":167,"line":224},[222,343,344],{"class":227},"if",[222,346,347],{"class":231}," source.labeling() ",[222,349,350],{"class":227},"is",[222,352,353],{"class":227}," not",[222,355,356],{"class":278}," None",[222,358,359],{"class":231},":\n",[222,361,362],{"class":167,"line":241},[222,363,364],{"class":231},"    target.setLabeling(source.labeling().clone())\n",[222,366,367],{"class":167,"line":248},[222,368,369],{"class":231},"    target.setLabelsEnabled(source.labelsEnabled())\n",[14,371,372,374,375,378,379,382,383,386],{},[189,373,322],{}," Two properties, both needed: the labelling configuration, and the flag that turns labelling on. Copying the first without the second produces a layer that is configured to label and does not, which is a puzzling ten minutes. ",[219,376,377],{},"labeling()"," returns ",[219,380,381],{},"None"," when the source has no labelling at all, so the check avoids an ",[219,384,385],{},"AttributeError"," on an unlabelled source.",[178,388,390],{"id":389},"copy-selected-style-categories","Copy selected style categories",[14,392,393],{},"For anything more than symbology, the style-category API says precisely what to bring across.",[212,395,397],{"className":214,"code":396,"language":216,"meta":217,"style":217},"from qgis.core import QgsMapLayer\n\ncategories = (QgsMapLayer.StyleCategory.Symbology\n              | QgsMapLayer.StyleCategory.Labeling\n              | QgsMapLayer.StyleCategory.Rendering)\n\nerror = target.importNamedStyle(source.exportNamedStyle(categories=categories))\n",[219,398,399,410,414,424,432,439,443],{"__ignoreMap":217},[222,400,401,403,405,407],{"class":167,"line":224},[222,402,228],{"class":227},[222,404,232],{"class":231},[222,406,235],{"class":227},[222,408,409],{"class":231}," QgsMapLayer\n",[222,411,412],{"class":167,"line":241},[222,413,245],{"emptyLinePlaceholder":244},[222,415,416,419,421],{"class":167,"line":248},[222,417,418],{"class":231},"categories ",[222,420,254],{"class":227},[222,422,423],{"class":231}," (QgsMapLayer.StyleCategory.Symbology\n",[222,425,426,429],{"class":167,"line":260},[222,427,428],{"class":227},"              |",[222,430,431],{"class":231}," QgsMapLayer.StyleCategory.Labeling\n",[222,433,434,436],{"class":167,"line":284},[222,435,428],{"class":227},[222,437,438],{"class":231}," QgsMapLayer.StyleCategory.Rendering)\n",[222,440,441],{"class":167,"line":303},[222,442,245],{"emptyLinePlaceholder":244},[222,444,445,448,450,453,457,459],{"class":167,"line":308},[222,446,447],{"class":231},"error ",[222,449,254],{"class":227},[222,451,452],{"class":231}," target.importNamedStyle(source.exportNamedStyle(",[222,454,456],{"class":455},"s9osk","categories",[222,458,254],{"class":227},[222,460,461],{"class":231},"categories))\n",[14,463,464,323,466,469,470,473,474,477,478,477,481,484,485,477,488,477,491,477,494,477,497,477,500,503,504,507,508,511],{},[189,465,322],{},[219,467,468],{},"exportNamedStyle()"," serialises the chosen categories to an XML document and ",[219,471,472],{},"importNamedStyle()"," reads it back into the target, which is the same mechanism as saving and loading a QML file without touching the disk. The categories are flags combined with the bitwise or, and the useful ones are ",[219,475,476],{},"Symbology",", ",[219,479,480],{},"Labeling",[219,482,483],{},"Rendering"," (opacity, blend mode, scale visibility), ",[219,486,487],{},"Fields",[219,489,490],{},"Forms",[219,492,493],{},"Actions",[219,495,496],{},"MapTips",[219,498,499],{},"AttributeTable",[219,501,502],{},"Diagrams"," and ",[219,505,506],{},"CustomProperties",". ",[219,509,510],{},"AllStyleCategories"," copies everything, which is right only between layers of genuinely identical structure — it brings field aliases, widget configuration and joins with it, and a mismatch produces an attribute table configured for fields that do not exist.",[14,513,514],{},[34,515,518,521,524,527,530,538,544,548,551,556,561,564,567,569,573,575,578,581,585,587,590,593,597,599],{"viewBox":516,"role":37,"ariaLabel":517,"xmlns":39},"0 0 760 250","Table matching common copying scenarios to the style categories that should be included in each",[41,519,520],{},"Which categories for which job",[45,522,523],{},"Copying between two years of the same dataset can use all categories. Copying a look between different datasets of the same geometry type should use symbology and rendering only. Applying a house style across a project should use symbology, labelling and rendering. Copying field configuration to a new extract of the same schema should use fields and forms without symbology.",[49,525],{"x":51,"y":51,"width":52,"height":526,"fill":54},"250",[73,528,529],{"x":75,"y":76,"style":77,"fill":78,"textAnchor":79},"Copy what applies, not everything",[49,531],{"x":532,"y":533,"width":534,"height":535,"rx":117,"fill":536,"stroke":109,"style":537},"16","46","330","30","#efeadd","stroke-width:1.5",[73,539,543],{"x":540,"y":541,"style":542,"fill":78,"textAnchor":79},"181","66","text-anchor:middle;font-size:11px;font-weight:bold;font-family:sans-serif","what you are doing",[49,545],{"x":546,"y":533,"width":547,"height":535,"rx":117,"fill":536,"stroke":109,"style":537},"354","390",[73,549,456],{"x":550,"y":541,"style":542,"fill":78,"textAnchor":79},"549",[49,552],{"x":532,"y":553,"width":534,"height":554,"rx":117,"fill":118,"stroke":109,"style":555},"82","38","stroke-width:1.2",[73,557,560],{"x":535,"y":558,"style":559,"fill":100},"106","font-size:11px;font-family:sans-serif","this year's extract of the same data",[49,562],{"x":546,"y":553,"width":547,"height":554,"rx":117,"fill":563,"stroke":119,"style":537},"#edf8e9",[73,565,510],{"x":566,"y":558,"style":559,"fill":100},"368",[49,568],{"x":532,"y":130,"width":534,"height":554,"rx":117,"fill":118,"stroke":109,"style":555},[73,570,572],{"x":535,"y":571,"style":559,"fill":100},"150","a different dataset, same look",[49,574],{"x":546,"y":130,"width":547,"height":554,"rx":117,"fill":88,"stroke":71,"style":537},[73,576,577],{"x":566,"y":571,"style":559,"fill":100},"Symbology and Rendering",[49,579],{"x":532,"y":580,"width":534,"height":554,"rx":117,"fill":118,"stroke":109,"style":555},"170",[73,582,584],{"x":535,"y":583,"style":559,"fill":100},"194","a house style across a project",[49,586],{"x":546,"y":580,"width":547,"height":554,"rx":117,"fill":88,"stroke":71,"style":537},[73,588,589],{"x":566,"y":583,"style":559,"fill":100},"Symbology, Labeling, Rendering",[49,591],{"x":532,"y":592,"width":534,"height":535,"rx":117,"fill":118,"stroke":109,"style":555},"214",[73,594,596],{"x":535,"y":595,"style":559,"fill":100},"234","field aliases onto a new extract",[49,598],{"x":546,"y":592,"width":547,"height":535,"rx":117,"fill":151,"stroke":152,"style":537},[73,600,601],{"x":566,"y":595,"style":559,"fill":100},"Fields and Forms only",[178,603,605],{"id":604},"apply-one-style-to-many-layers","Apply one style to many layers",[212,607,609],{"className":214,"code":608,"language":216,"meta":217,"style":217},"def apply_style(source, targets, categories):\n    document = source.exportNamedStyle(categories=categories)\n    applied, skipped = [], []\n\n    for layer in targets:\n        if layer.geometryType() != source.geometryType():\n            skipped.append(layer.name())\n            continue\n        layer.importNamedStyle(document)\n        layer.triggerRepaint()\n        applied.append(layer.name())\n\n    return applied, skipped\n\n\npolygons = [l for l in QgsProject.instance().mapLayers().values()\n            if hasattr(l, \"geometryType\")]\napplied, skipped = apply_style(source, polygons, categories)\nprint(f\"styled {len(applied)}, skipped {len(skipped)}: {skipped}\")\n",[219,610,611,623,640,650,654,668,682,687,692,698,704,710,715,724,729,734,756,774,785],{"__ignoreMap":217},[222,612,613,616,620],{"class":167,"line":224},[222,614,615],{"class":227},"def",[222,617,619],{"class":618},"svObZ"," apply_style",[222,621,622],{"class":231},"(source, targets, categories):\n",[222,624,625,628,630,633,635,637],{"class":167,"line":241},[222,626,627],{"class":231},"    document ",[222,629,254],{"class":227},[222,631,632],{"class":231}," source.exportNamedStyle(",[222,634,456],{"class":455},[222,636,254],{"class":227},[222,638,639],{"class":231},"categories)\n",[222,641,642,645,647],{"class":167,"line":248},[222,643,644],{"class":231},"    applied, skipped ",[222,646,254],{"class":227},[222,648,649],{"class":231}," [], []\n",[222,651,652],{"class":167,"line":260},[222,653,245],{"emptyLinePlaceholder":244},[222,655,656,659,662,665],{"class":167,"line":284},[222,657,658],{"class":227},"    for",[222,660,661],{"class":231}," layer ",[222,663,664],{"class":227},"in",[222,666,667],{"class":231}," targets:\n",[222,669,670,673,676,679],{"class":167,"line":303},[222,671,672],{"class":227},"        if",[222,674,675],{"class":231}," layer.geometryType() ",[222,677,678],{"class":227},"!=",[222,680,681],{"class":231}," source.geometryType():\n",[222,683,684],{"class":167,"line":308},[222,685,686],{"class":231},"            skipped.append(layer.name())\n",[222,688,689],{"class":167,"line":314},[222,690,691],{"class":227},"            continue\n",[222,693,695],{"class":167,"line":694},9,[222,696,697],{"class":231},"        layer.importNamedStyle(document)\n",[222,699,701],{"class":167,"line":700},10,[222,702,703],{"class":231},"        layer.triggerRepaint()\n",[222,705,707],{"class":167,"line":706},11,[222,708,709],{"class":231},"        applied.append(layer.name())\n",[222,711,713],{"class":167,"line":712},12,[222,714,245],{"emptyLinePlaceholder":244},[222,716,718,721],{"class":167,"line":717},13,[222,719,720],{"class":227},"    return",[222,722,723],{"class":231}," applied, skipped\n",[222,725,727],{"class":167,"line":726},14,[222,728,245],{"emptyLinePlaceholder":244},[222,730,732],{"class":167,"line":731},15,[222,733,245],{"emptyLinePlaceholder":244},[222,735,737,740,742,745,748,751,753],{"class":167,"line":736},16,[222,738,739],{"class":231},"polygons ",[222,741,254],{"class":227},[222,743,744],{"class":231}," [l ",[222,746,747],{"class":227},"for",[222,749,750],{"class":231}," l ",[222,752,664],{"class":227},[222,754,755],{"class":231}," QgsProject.instance().mapLayers().values()\n",[222,757,759,762,765,768,771],{"class":167,"line":758},17,[222,760,761],{"class":227},"            if",[222,763,764],{"class":278}," hasattr",[222,766,767],{"class":231},"(l, ",[222,769,770],{"class":271},"\"geometryType\"",[222,772,773],{"class":231},")]\n",[222,775,777,780,782],{"class":167,"line":776},18,[222,778,779],{"class":231},"applied, skipped ",[222,781,254],{"class":227},[222,783,784],{"class":231}," apply_style(source, polygons, categories)\n",[222,786,788,791,794,797,800,803,806,809,812,814,817,819,822,825,828,830,833],{"class":167,"line":787},19,[222,789,790],{"class":278},"print",[222,792,793],{"class":231},"(",[222,795,796],{"class":227},"f",[222,798,799],{"class":271},"\"styled ",[222,801,802],{"class":278},"{len",[222,804,805],{"class":231},"(applied)",[222,807,808],{"class":278},"}",[222,810,811],{"class":271},", skipped ",[222,813,802],{"class":278},[222,815,816],{"class":231},"(skipped)",[222,818,808],{"class":278},[222,820,821],{"class":271},": ",[222,823,824],{"class":278},"{",[222,826,827],{"class":231},"skipped",[222,829,808],{"class":278},[222,831,832],{"class":271},"\"",[222,834,835],{"class":231},")\n",[14,837,838,840,841,844,845,848,849,852,853,855],{},[189,839,322],{}," Exporting once and importing many times is faster than cloning per layer and, more usefully, guarantees every target gets an identical style. The geometry-type check prevents the quiet no-op of applying a polygon renderer to a point layer; reporting what was skipped is what stops that being a mystery later. The ",[219,842,843],{},"hasattr"," filter excludes raster layers, which have no ",[219,846,847],{},"geometryType()"," — a cleaner alternative on newer releases is checking ",[219,850,851],{},"layer.type()"," against the vector layer type. Note that ",[219,854,472],{}," returns a tuple of success and message on some paths; checking it is worthwhile in a script that must not silently do nothing.",[178,857,859],{"id":858},"keep-several-styles-on-one-layer","Keep several styles on one layer",[14,861,862],{},"A layer can carry named styles and switch between them, which is how one project offers a printed look and a screen look.",[212,864,866],{"className":214,"code":865,"language":216,"meta":217,"style":217},"manager = target.styleManager()\n\nmanager.addStyleFromLayer(\"Print\")            # capture the current style under a name\ntarget.setRenderer(screen_renderer)\nmanager.addStyleFromLayer(\"Screen\")\n\nmanager.setCurrentStyle(\"Print\")\nprint(manager.styles(), manager.currentStyle())\n",[219,867,868,878,882,897,902,911,915,924],{"__ignoreMap":217},[222,869,870,873,875],{"class":167,"line":224},[222,871,872],{"class":231},"manager ",[222,874,254],{"class":227},[222,876,877],{"class":231}," target.styleManager()\n",[222,879,880],{"class":167,"line":241},[222,881,245],{"emptyLinePlaceholder":244},[222,883,884,887,890,893],{"class":167,"line":248},[222,885,886],{"class":231},"manager.addStyleFromLayer(",[222,888,889],{"class":271},"\"Print\"",[222,891,892],{"class":231},")            ",[222,894,896],{"class":895},"sjoCn","# capture the current style under a name\n",[222,898,899],{"class":167,"line":260},[222,900,901],{"class":231},"target.setRenderer(screen_renderer)\n",[222,903,904,906,909],{"class":167,"line":284},[222,905,886],{"class":231},[222,907,908],{"class":271},"\"Screen\"",[222,910,835],{"class":231},[222,912,913],{"class":167,"line":303},[222,914,245],{"emptyLinePlaceholder":244},[222,916,917,920,922],{"class":167,"line":308},[222,918,919],{"class":231},"manager.setCurrentStyle(",[222,921,889],{"class":271},[222,923,835],{"class":231},[222,925,926,928],{"class":167,"line":314},[222,927,790],{"class":278},[222,929,930],{"class":231},"(manager.styles(), manager.currentStyle())\n",[14,932,933,323,935,938,939,942,943,203],{},[189,934,322],{},[219,936,937],{},"addStyleFromLayer()"," snapshots the layer's current styling under a name, so the workflow is: style the layer, save it as a name, restyle, save that too. Switching with ",[219,940,941],{},"setCurrentStyle()"," changes the layer's appearance instantly and is remembered in the project. This is the mechanism behind the style combo in the layer properties dialog, and it pairs well with layouts: a map item locked to a map theme can render the print style while the canvas shows the screen one, as described in ",[26,944,946],{"href":945},"\u002Fspatial-data-processing-automation\u002Fautomated-map-layout-generation\u002Fadd-map-item-and-set-extent-pyqgis\u002F","Add a Map Item and Set Its Extent in PyQGIS",[14,948,949],{},[34,950,953,956,959,962,969,972,978,982,986,991,996,1002,1005,1010,1013,1017,1021,1024,1028,1035,1038],{"viewBox":951,"role":37,"ariaLabel":952,"xmlns":39},"0 0 760 244","Diagram of one layer carrying two named styles, a screen style and a print style, with the current style deciding what is drawn",[41,954,955],{},"One layer, two styles, switched by name",[45,957,958],{},"A layer holds several named styles in its style manager. A screen style might use bright fills and larger labels for quick reading, while a print style uses muted fills and finer line work. Setting the current style changes the appearance instantly, and the choice is remembered in the project.",[49,960],{"x":51,"y":51,"width":52,"height":961,"fill":54},"244",[56,963,964],{},[59,965,967],{"id":966,"viewBox":62,"refX":63,"refY":64,"markerWidth":65,"markerHeight":65,"orient":66},"styMgrArrow",[68,968],{"d":70,"fill":71},[73,970,971],{"x":75,"y":76,"style":77,"fill":78,"textAnchor":79},"The same data, dressed for two different jobs",[49,973],{"x":974,"y":975,"width":976,"height":977,"rx":87,"fill":88,"stroke":71,"style":89},"284","48","192","56",[73,979,981],{"x":75,"y":980,"style":94,"fill":71,"textAnchor":79},"72","one layer",[73,983,985],{"x":75,"y":984,"style":99,"fill":100,"textAnchor":79},"92","styleManager()",[49,987],{"x":988,"y":170,"width":989,"height":990,"rx":63,"fill":151,"stroke":152,"style":120},"40","300","80",[73,992,995],{"x":993,"y":994,"style":542,"fill":152,"textAnchor":79},"190","164","Screen",[49,997],{"x":998,"y":999,"width":988,"height":83,"rx":1000,"fill":152,"fillOpacity":1001,"stroke":152,"style":537},"64","176","3",0.5,[49,1003],{"x":1004,"y":999,"width":988,"height":83,"rx":1000,"fill":119,"fillOpacity":1001,"stroke":119,"style":537},"112",[73,1006,1009],{"x":1007,"y":976,"style":1008,"fill":100},"230","font-size:10px;font-family:sans-serif","bright, larger labels",[49,1011],{"x":1012,"y":170,"width":989,"height":990,"rx":63,"fill":118,"stroke":109,"style":120},"420",[73,1014,1016],{"x":1015,"y":994,"style":542,"fill":78,"textAnchor":79},"570","Print",[49,1018],{"x":1019,"y":999,"width":988,"height":83,"rx":1000,"fill":152,"fillOpacity":1020,"stroke":109,"style":555},"444",0.22,[49,1022],{"x":1023,"y":999,"width":988,"height":83,"rx":1000,"fill":119,"fillOpacity":1020,"stroke":109,"style":555},"492",[73,1025,1027],{"x":1026,"y":976,"style":1008,"fill":100},"610","muted, finer lines",[167,1029],{"x1":1030,"y1":1031,"x2":1032,"y2":1033,"stroke":71,"style":1034},"340","104","220","134","stroke-width:2;marker-end:url(#styMgrArrow)",[167,1036],{"x1":1012,"y1":1031,"x2":1037,"y2":1033,"stroke":71,"style":1034},"540",[73,1039,1040],{"x":75,"y":595,"style":99,"fill":109,"textAnchor":79},"setCurrentStyle switches instantly, and the project remembers the choice",[178,1042,1044],{"id":1043},"when-the-fields-do-not-match","When the fields do not match",[14,1046,1047],{},"A categorized or graduated renderer refers to a field by name, and copying it to a layer without that field produces a layer where every feature falls into no category — visible as an unstyled or invisible layer rather than an error.",[14,1049,1050,1051,1054,1055,1058,1059,1062,1063,1066,1067,203],{},"Three ways out, in order of preference. ",[189,1052,1053],{},"Rename the field"," in the target if it is genuinely the same attribute under a different name; the style then applies unchanged and everything downstream stays simple. ",[189,1056,1057],{},"Rewrite the renderer's attribute"," after copying, with ",[219,1060,1061],{},"renderer.setClassAttribute(\"new_field\")"," for categorized and graduated renderers, which is a single line and keeps the colours and breaks. ",[189,1064,1065],{},"Rebuild the categories"," from the target's own values when the classification itself differs, as in ",[26,1068,1070],{"href":1069},"\u002Fpyqgis-cartography-visualization\u002Fgraduated-categorized-renderers\u002Fcreate-categorized-renderer-pyqgis\u002F","Create a Categorized Renderer in PyQGIS",[212,1072,1074],{"className":214,"code":1073,"language":216,"meta":217,"style":217},"renderer = target.renderer()\nif hasattr(renderer, \"setClassAttribute\"):\n    renderer.setClassAttribute(\"landuse_code\")\n    target.triggerRepaint()\n",[219,1075,1076,1086,1101,1111],{"__ignoreMap":217},[222,1077,1078,1081,1083],{"class":167,"line":224},[222,1079,1080],{"class":231},"renderer ",[222,1082,254],{"class":227},[222,1084,1085],{"class":231}," target.renderer()\n",[222,1087,1088,1090,1092,1095,1098],{"class":167,"line":241},[222,1089,344],{"class":227},[222,1091,764],{"class":278},[222,1093,1094],{"class":231},"(renderer, ",[222,1096,1097],{"class":271},"\"setClassAttribute\"",[222,1099,1100],{"class":231},"):\n",[222,1102,1103,1106,1109],{"class":167,"line":248},[222,1104,1105],{"class":231},"    renderer.setClassAttribute(",[222,1107,1108],{"class":271},"\"landuse_code\"",[222,1110,835],{"class":231},[222,1112,1113],{"class":167,"line":260},[222,1114,1115],{"class":231},"    target.triggerRepaint()\n",[14,1117,1118,1120,1121,1123,1124,1127],{},[189,1119,322],{}," The ",[219,1122,843],{}," guard is there because a single-symbol or rule-based renderer has no class attribute, and a script applying a style across mixed layers will meet both. Checking rather than assuming keeps the helper usable everywhere. After changing the attribute the category ",[18,1125,1126],{},"values"," still refer to the old field's contents, so this only helps when the two fields hold the same vocabulary — otherwise the catch-all category is doing all the work and it is time to rebuild.",[178,1129,1131],{"id":1130},"qgis-version-compatibility","QGIS version compatibility",[1133,1134,1135,1151],"table",{},[1136,1137,1138],"thead",{},[1139,1140,1141,1145,1148],"tr",{},[1142,1143,1144],"th",{},"QGIS version",[1142,1146,1147],{},"Python",[1142,1149,1150],{},"Notes",[1152,1153,1154,1168,1178,1193],"tbody",{},[1139,1155,1156,1160,1163],{},[1157,1158,1159],"td",{},"3.22 LTR",[1157,1161,1162],{},"3.9",[1157,1164,1165,1167],{},[219,1166,326],{},", style categories and the style manager all present.",[1139,1169,1170,1173,1175],{},[1157,1171,1172],{},"3.28 LTR",[1157,1174,1162],{},[1157,1176,1177],{},"Identical.",[1139,1179,1180,1183,1186],{},[1157,1181,1182],{},"3.34 LTR",[1157,1184,1185],{},"3.12",[1157,1187,1188,1189,1192],{},"Baseline for this page; scoped ",[219,1190,1191],{},"QgsMapLayer.StyleCategory"," names available.",[1139,1194,1195,1198,1200],{},[1157,1196,1197],{},"3.40 \u002F 3.44",[1157,1199,1185],{},[1157,1201,1202],{},"Identical; further categories added for newer layer types.",[14,1204,1205,1206,203],{},"Styles can also travel as QML files on disk, which is the right choice when the style must be shared between projects or committed to a repository — see ",[26,1207,1209],{"href":1208},"\u002Fpyqgis-cartography-visualization\u002Fprogrammatic-layer-styling\u002Fsave-and-load-qml-style-pyqgis\u002F","Save and Load a QML Style in PyQGIS",[178,1211,1213],{"id":1212},"troubleshooting","Troubleshooting",[183,1215,1216,1224,1230,1239,1247,1257],{},[186,1217,1218,1221,1222,203],{},[189,1219,1220],{},"Changing one layer changes another."," The renderer was assigned rather than cloned. Always ",[219,1223,326],{},[186,1225,1226,1229],{},[189,1227,1228],{},"The target layer is invisible after copying."," A categorized renderer on a field the target does not have. Rewrite the class attribute or rebuild.",[186,1231,1232,1235,1236,203],{},[189,1233,1234],{},"Labels did not come across."," Labelling is separate. Copy it and set ",[219,1237,1238],{},"setLabelsEnabled(True)",[186,1240,1241,323,1244,1246],{},[189,1242,1243],{},"The attribute table looks wrong.",[219,1245,510],{}," brought field configuration from a differently shaped layer. Copy only symbology and labelling.",[186,1248,1249,1252,1253,1256],{},[189,1250,1251],{},"Nothing happened at all."," Geometry types differ, or ",[219,1254,1255],{},"triggerRepaint()"," was not called.",[186,1258,1259,1262],{},[189,1260,1261],{},"A saved style reverted."," The project was not saved, or the layer's current style was switched back by the style manager.",[178,1264,1266],{"id":1265},"conclusion","Conclusion",[14,1268,1269,1270,1272],{},"Clone the renderer rather than assigning it, copy labelling separately along with its enabled flag, and use ",[219,1271,468],{}," with explicit categories when more than symbology should travel. Export once and import many times when styling a set of layers, check geometry types and report what was skipped, and when the target's fields differ, rewrite the renderer's class attribute rather than accepting a layer that quietly renders nothing.",[178,1274,1276],{"id":1275},"frequently-asked-questions","Frequently Asked Questions",[14,1278,1279,1282],{},[189,1280,1281],{},"What is the difference between copying a style and loading a QML?","\nNone in substance — a QML is the same serialised style on disk. Copy in memory within one script, use a QML when the style must outlive it or be shared.",[14,1284,1285,1288],{},[189,1286,1287],{},"Can I copy a style from a raster to a vector layer?","\nNo. Their styling models are unrelated. Raster styles copy to other rasters the same way.",[14,1290,1291,1294,1295,1298],{},[189,1292,1293],{},"Does copying a style bring the layer's coordinate system?","\nOnly if the ",[219,1296,1297],{},"CRS"," category is included, and doing so is almost never wanted — it changes how the data is interpreted, not how it looks.",[14,1300,1301,1304],{},[189,1302,1303],{},"How do I copy just the colours?","\nThere is no colour-only category. Clone the renderer and change what should differ, or extract the colour ramp and apply it to a renderer you build.",[14,1306,1307,1310],{},[189,1308,1309],{},"Can I apply a style to a layer that is not in the project?","\nYes. Styling belongs to the layer object, so a layer built in a script and never added can be styled and then exported.",[14,1312,1313,1316],{},[189,1314,1315],{},"Does the style survive an export to GeoPackage?","\nYes — a GeoPackage can store layer styles, and QGIS offers to save them there. A shapefile cannot, which is one more reason to prefer GeoPackage.",[178,1318,1320],{"id":1319},"related","Related",[183,1322,1323,1328,1332,1336,1340],{},[186,1324,1325,1327],{},[26,1326,29],{"href":28}," — the guide this recipe belongs to",[186,1329,1330],{},[26,1331,1209],{"href":1208},[186,1333,1334],{},[26,1335,202],{"href":201},[186,1337,1338],{},[26,1339,1070],{"href":1069},[186,1341,1342],{},[26,1343,1345],{"href":1344},"\u002Fpyqgis-cartography-visualization\u002Flabeling-and-annotations\u002Fcontrol-label-placement-and-collisions-pyqgis\u002F","Control Label Placement and Collisions in PyQGIS",[1347,1348,1349],"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 .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sjoCn, html code.shiki .sjoCn{--shiki-default:#9AA79F}",{"title":217,"searchDepth":241,"depth":241,"links":1351},[1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362],{"id":180,"depth":241,"text":181},{"id":206,"depth":241,"text":207},{"id":389,"depth":241,"text":390},{"id":604,"depth":241,"text":605},{"id":858,"depth":241,"text":859},{"id":1043,"depth":241,"text":1044},{"id":1130,"depth":241,"text":1131},{"id":1212,"depth":241,"text":1213},{"id":1265,"depth":241,"text":1266},{"id":1275,"depth":241,"text":1276},{"id":1319,"depth":241,"text":1320},"Apply one layer's styling to another from code — clone the renderer, copy labelling and other style categories selectively, use the style manager, and handle layers whose fields do not match.","md",{"slug":1366,"type":1367,"breadcrumb":1368,"datePublished":1369,"dateModified":1369},"copy-style-between-layers-pyqgis","article","Copy a Style","2026-08-15","\u002Fpyqgis-cartography-visualization\u002Fprogrammatic-layer-styling\u002Fcopy-style-between-layers-pyqgis",{"title":5,"description":1363},"pyqgis-cartography-visualization\u002Fprogrammatic-layer-styling\u002Fcopy-style-between-layers-pyqgis\u002Findex","d--veyXN5Q41cs1x6mDHTKMUUBOYR-FQwFQtj_UD2qY",1786789584618]