7

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?

7

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): enter image description here

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)
  • I want to achieve using python script. my objective is to change the selection symbol. – Keyur Parmar Dec 23 '15 at 7:07
  • @KeyurParmar I have edited the answer to include 2 possible ways to go in Python scripts. Good luck. – Detlev Dec 23 '15 at 12:43
  • Thanks, i have tired 2nd option and it is working for me.. – Keyur Parmar Dec 24 '15 at 6:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.