I have a layer with different informations. I want to change the selected polygon color to "Transparent". I am able to achieve that using:
iface.mapCanvas().setSelectionColor( QColor("Transparent") )
But I want a different border color such as red or any other color. For an example in ArcMap, there is an option to set the border color, border width and many more.
How can I achieve that using python script in QGIS?
Answer
Some time ago I had a similar problem (How to change the symbology of selected features in QGIS). It seems that this features isn't available in QGIS 2.12 yet (https://hub.qgis.org/issues/12879), so you can achieve this effect using isselected
function, available in Nathan's plugin qgsexpressionplus (https://github.com/NathanW2/qgsexpressionsplus).
For example to to change the border color of selected polygons override it with data defined property (QGIS 2.12):
if( isselected( @layer_id ), color_rgb( 255, 0, 0), color_rgb(0, 0, 255) )
When variable @layer_id
is not available (eg QGIS 2.8.x) give the layername as argument.
However I am faced with the problem that the False case for features not being selected will get executed, but not the True case when features are selected. As workaround set the default border color to the color of selected features, and the border color of the not selected features as data defined property.
See this example, where color_rgb(255,0,0) takes no effect (labels show select state):
Set similar expressions for other symbol properties, eg. border width.
AFAIK to change symbol properties for selected objects in Python there are only workarounds. It seems not possible to change the border color, since the builtin settings of selected feature are superior .
1) Mimic in Python what qgsexpressionplus plugin does. Use it to change the border width from 1 to 4 in selected state.
from qgis.utils import qgsfunction
from qgis.core import QgsExpression, QgsMapLayerRegistry
@qgsfunction(1, group='auto', register=False)
def isselected(values, feature, parent):
layername=values[0]
fid = feature.id()
layers = QgsMapLayerRegistry.instance().mapLayers()
try:
layer = layers[layername]
except KeyError:
try:
layer = [l for l in layers.iteritems() if l[1].name() == layername][0][1]
except IndexError:
parent.setEvalErrorString( u'No layer with id or name {} found'.format( layername ) )
return False
return fid in layer.selectedFeaturesIds()
QgsExpression.registerFunction(isselected)
layer = iface.activeLayer()
symb = layer.rendererV2().symbols()[0]
symb.deleteSymbolLayer(0)
slyr = QgsSimpleFillSymbolLayerV2.create({'width_border_expression': 'if( isselected( \'' + layer.name() + '\' ), 4, 1)'})
symb.appendSymbolLayer(slyr) iface.mapCanvas().refresh()
2) Use QgsHighlight features. This requires to write a function (slot) and connect it to the selectionChanged() signal of the layer. When features are selected another geometry, the highlight geometry, is created. When the feature is not selected any more, highlight geometry is deleted.
Remember that you do not change the selection symbology, but you create another geometry which sits on top of the selection symbol.
This is the way to go:
from qgis.gui import QgsHighlight
from PyQt4.QtGui import QColor
h_list = []
# function that does the work of highlighting selected features
def highlight_features():
global h_list
# remove all highlight objects
for h in range(len(h_list)):
h_list.pop(h)
# create highlight geometries for selected objects
for i in layer.selectedFeatures():
h = QgsHighlight(iface.mapCanvas(), i.geometry(), layer)
# set highlight symbol properties
h.setColor(QColor(255,0,0,255))
h.setWidth(6)
h.setFillColor(QColor(255,255,255,0))
# write the object to the list
h_list.append(h)
# connect the function to the layer signal
layer.selectionChanged.connect(highlight_features)
Clean up the connection when you don't use it anymore:
layer.selectionChanged.disconnect(highlight_features)
No comments:
Post a Comment