tag:blogger.com,1999:blog-78677289216933795192024-03-12T20:10:46.433-07:00PyQGIS like a Boss...even with bad or nonexistent documentation.Doctr1nehttp://www.blogger.com/profile/00185919767173459558noreply@blogger.comBlogger3125tag:blogger.com,1999:blog-7867728921693379519.post-38920998303015249542012-10-31T08:28:00.003-07:002012-11-01T02:11:17.834-07:00Basics: Setting a custom symbology for QGIS-layersSo you want to use a custom symbology for your layers and achieve that through Python.<br />
<br />
Let me tell you first: The easy way is the WRONG way!<br />
Because QGIS<b> </b>crashes with a "Win32RuntimeException" if you try the easy way.<br />
So <b>DON'T GO THERE</b> and brace yourself for a detour!<br />
<br />
Instead of creating a new Symbol, which contains all the fancy SymbologyLayers with your amazing Arrowheads for PolyLines and whatnot, you create just your beautiful SymbologyLayers and add it to the pre-existing Symbol.
<br />
<br />
This example shows a function which you can use to set a symbologystyle for a PolyLine-Layer with two styles to choose from: Awesome Arrowheads for your lines, or ugly dots.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-nEOo4oV0gLA/UJFEl8q3L7I/AAAAAAAAABQ/KMuB64Pcpek/s1600/arrow.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="http://3.bp.blogspot.com/-nEOo4oV0gLA/UJFEl8q3L7I/AAAAAAAAABQ/KMuB64Pcpek/s400/arrow.png" width="378" /></a></div>
<br />
<br />
<pre style="background-image: URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> # adds a LineLayerStyle (Arrow, dotted)
def setLineLayerStyle(self, layer, style):
if(style == "arrow"):
sl = QgsSymbolLayerV2Registry.instance().symbolLayerMetadata("LineDecoration").createSymbolLayer({ 'width' : '0.26', 'color' : '0,0,0' })
symbollist = layer.rendererV2().symbols()
symbol = symbollist[0]
symbol.appendSymbolLayer(sl)
elif(style == "dotted"):
sl = QgsSymbolLayerV2Registry.instance().symbolLayerMetadata("MarkerLine").createSymbolLayer({ 'width' : '0.26', 'color' : '0,0,0' })
symbollist = layer.rendererV2().symbols()
symbol = symbollist[0]
symbol.appendSymbolLayer(sl)
self.canvas.refresh()
</code></pre>
<br />
Done.
<br />
<br />
What can i use instead of bloody arrows or dots you ask?!
Read the <a href="http://www.qgis.org/pyqgis-cookbook/" target="_blank">pyqgis-cookbook</a> or something.<br />
<br />
or don't....because you wouldn't find it there in the first place.Doctr1nehttp://www.blogger.com/profile/00185919767173459558noreply@blogger.com0tag:blogger.com,1999:blog-7867728921693379519.post-3847137877548930092012-10-31T04:17:00.005-07:002012-11-01T01:29:03.727-07:00Basics: Automatic use of a CRS for new layersYou are creating your own layers in QGIS through Python? Good job.<br />
<br />
But everytime you do that QGIS punches you in the face with a prompt to select the coordinate-reference-system you want for the new layer.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-ZwrjGJVgD3M/UJEIiki2XGI/AAAAAAAAAAw/XQxe3g3lQnw/s1600/prompt.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="" border="0" height="302" src="http://1.bp.blogspot.com/-ZwrjGJVgD3M/UJEIiki2XGI/AAAAAAAAAAw/XQxe3g3lQnw/s400/prompt.png" title="PROMPTS EVERYWHERE!" width="400" /></a></div>
<br />
To get rid of all that you need tell QGIS that you don't want that...easy right. <br />
<br />
First you create a settings-variable. And because QGIS ist awesome you just use the PyQt4-Class QSettings. Then you set the value of "/Projections/defaultBehaviour" to whatever you need.
There are three possibilities:<br />
<ul>
<li>"useGlobal" (use a preset CRS everytime)</li>
<li>"useProject" (use the Project-CRS)</li>
<li>"prompt" (use the stupid prompt thingy)</li>
</ul>
<pre style="background-image: URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> 'set new Layers to use the Project-CRS'
def enableUseOfGlobalCrs(self):
self.s = QSettings()
self.oldValidation = self.s.value("/Projections/defaultBehaviour").toString()
self.s.setValue( "/Projections/defaultBehaviour", "useProject" )
'enable old settings again'
def disableUseOfGlobalCrs(self):
self.s.setValue( "/Projections/defaultBehaviour", self.oldValidation )
</code></pre>
<br />
Done.
Doctr1nehttp://www.blogger.com/profile/00185919767173459558noreply@blogger.com3tag:blogger.com,1999:blog-7867728921693379519.post-11782979582771349992012-10-31T03:43:00.002-07:002012-11-01T01:29:15.772-07:00Basics: Creating a new layer in QGIS with PythonYou want to create a new layer out of python programmatically...no worries.<br />
<br />
Just create a new layerobject like this:<br />
<br />
<pre style="background-image: URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> from qgis.core import QgsVectorLayer, QgsField, QgsMapLayerRegistry
from PyQt4.QtCore import QVariant
'create Layer'
self.lineLayer = QgsVectorLayer("LineString", name, "memory")
</code></pre>
<br />
<b>LineString</b> is the type of layer you want to create. (e.g. Point, LineString or Polygon)<br />
<b>name</b> is obviously the displayed name of the layer.<br />
<b>memory</b> is the storagetype. it is just an unsaved memorylayer in this example.
<br />
<br />
After that you need to specifiy the layerattributes. (if you want to)<br />
To do that you have to get the dataprovider of the layer and set it to "editable" to add the attributes you want the included features to have. To commit your changes to the attributetable use the commitChanges()-Function of the QgsVectorLayer.<br />
<br />
<pre style="background-image: URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> 'set Attributes'
self.lineLayer.startEditing()
self.layerData = self.lineLayer.dataProvider()
self.layerData.addAttributes([ QgsField("ID", QVariant.String), QgsField("latStart", QVariant.String), QgsField("lonStart", QVariant.String), QgsField("latEnd", QVariant.String), QgsField("lonEnd", QVariant.String) ])#
self.lineLayer.commitChanges()
</code></pre>
<br />
Now the fresh layer needs to be added to the MapLayerRegistry within QGIS so it is out there for the world to see.
<br />
<br />
<pre style="background-image: URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> 'show Layer in QGIS'
QgsMapLayerRegistry.instance().addMapLayer(self.lineLayer)
</code></pre>
<br />
Done.Doctr1nehttp://www.blogger.com/profile/00185919767173459558noreply@blogger.com1