5

Currently the following code-snip works great to highlight a shape based on the 'feature' and 'layer' variables:

    self.rubberHighlight = QgsRubberBand(self.iface.mapCanvas(),QGis.Polygon)
    self.rubberHighlight.setBorderColor(QtGui.QColor(0,0,255))
    self.rubberHighlight.setFillColor(QtGui.QColor(0,0,0,0))
    self.rubberHighlight.setLineStyle(Qt.PenStyle(Qt.DotLine))
    self.rubberHighlight.setWidth(3)
    self.rubberHighlight.setToGeometry(feature, layer)
    self.rubberHighlight.show()

Upon creating a highlight, I am able to remove singular instances with...

    self.iface.mapCanvas().scene().removeItem(self.rubberHighlight)
    del self.rubberHighlight

... yet this does not work for multiple rubberband highlighted features simultaneously.

Any clues on how to add and remove many highlights at once?

UPDATED (DIRTY) SOLUTION:

def __init__(self, iface, ..., parent=None):
    ...
    self.rbDict = {}
    ...
    self.show()

def selectedRow(self):
    selectedIndexes = self.cellSelectionModel.selectedRows()
    if len(selectedIndexes)<=0:
        self.clearRubberBandHighlights()
        return
    else:
        for index in selectedIndexes:
            row = index.row()
            layerAndFeatureIDs = self.tableData.data(self.tableData.index(row,0),Qt.DisplayRole)
            if layerAndFeatureIDs==None:
                self.clearRubberBandHighlights()
                return
            else:
                self.clearRubberBandHighlights()
                if 'Layer' in self.editorType or 'Stress Period' in self.editorType:
                    single = None
                    try:
                        layerId,featureId = [layerAndFid for layerAndFid \
                                             in layerAndFeatureIDs.split('~:#>')]
                        single = True
                    except:
                        layerIds = []
                        featureIds = []
                        eachLayerFidPair = list(set([pair for pair \
                                                     in layerAndFeatureIDs.split('}${')]))
                        for pair in eachLayerFidPair:
                            layerId,featureId = [layerAndFid for layerAndFid \
                                                 in pair.split('~:#>')]
                            layerIds.append(layerId)
                            featureIds.append(featureId)
                        single = False
                    if single:
                        layerRef = ftools_utils.getMapLayerByName(unicode(layerId))
                        for feature in layerRef.getFeatures():
                            if int(feature.id())==int(featureId):
                                self.rubberBandHighlight(feature,layerRef)
                    elif not single:
                        for layIdx, layerId in enumerate(layerIds):
                            layerRef = ftools_utils.getMapLayerByName(unicode(layerId))
                            for feature in layerRef.getFeatures():
                                if int(feature.id())==int(featureIds[layIdx]):
                                    self.rubberBandHighlight(feature,layerRef)

def rubberBandHighlight(self,feature,layer):
    self.rbDict[feature.id()] = QgsRubberBand(self.iface.mapCanvas(),True)
    self.rbDict[feature.id()].setBorderColor(QtGui.QColor(0,0,255))
    self.rbDict[feature.id()].setFillColor(QtGui.QColor(0,0,0,0))
    self.rbDict[feature.id()].setLineStyle(Qt.PenStyle(Qt.DotLine))
    self.rbDict[feature.id()].setWidth(3)
    self.rbDict[feature.id()].addGeometry(feature.geometry(),None)

def clearRubberBandHighlights(self):
    for key in self.rbDict.keys():
        self.iface.mapCanvas().scene().removeItem(self.rbDict[key])
        del self.rbDict[key]

EXAMPLE INPUT DATA (as present in QtableView):

(where each sublist index[0] contains a special delimited string of all layer and feature.id() information)

[Aquitards~:#>1,Aquitard 2,1,2,,,,,,,,,,,],
[Aquitards~:#>0}${Aquitards~:#>0}${Aquitards~:#>2,Aquitard 1;Aquitard 8;Aquitard 3,1,3,,,,,,,,,,,],
[Aquitards~:#>2}${Aquitards~:#>1,Aquitard 7;Aquitard 9,1,4,,,,,,,,,,,]
5
  • Not completely sure but from the QGIS docs, you could perhaps try self.rubberHighlight.reset or self.rubberHighlight.reset(QGis.Polygon)? – Joseph May 5 '15 at 10:05
  • So, did the answer work for you? – Germán Carrillo May 11 '15 at 16:30
  • @gcarrillo: It is still in a state of testing - but I can confirm that the advice Joseph made did not solve the problem. Testing your answer seems like it might be successful - yet unknown for couple more days... – Katalpa May 11 '15 at 17:00
  • @Katalpa Ok, nice to get some feedback. – Germán Carrillo May 11 '15 at 18:49
  • 1
    @gcarrillo, I hope the delay is no offence. Receiving much trouble in a python prep-step which much be done prior...stackoverflow.com/questions/30170442/… – Katalpa May 11 '15 at 19:10
6

This should work for a polygon layer (I've tested it in the QGIS Python console, QGIS v.2.8.1):

from qgis.gui import QgsRubberBand
from PyQt4.QtGui import QColor

rbDict = {} # We need this to store the rbs we'll create
layer = iface.activeLayer()

# Create rubber bands
for f in layer.getFeatures():
  fId=f.id()
  rbDict[fId] = QgsRubberBand(iface.mapCanvas(), True)
  rbDict[fId].setColor( QColor( 0,255,0,255 ) )
  rbDict[fId].setWidth( 2 )
  rbDict[fId].addGeometry(f.geometry(), None) 

# And then remove them
for f in layer.getFeatures():
  fId=f.id()
  iface.mapCanvas().scene().removeItem(rbDict[fId])
  del rbDict[fId]

As you may already know, you would use almost the same code for lines (just switching the boolean parameter to False in the instantiation of the rubber band) and you would need to use QgsVertexMarker for points.

Tell me if something isn't clear.

3
  • Your answer appears to be the right direction - however implementing with circumstances of multiple features from multiple layers seems to be troublesome. Will post update soon. – Katalpa May 12 '15 at 1:06
  • I have updated the original post with the current (dirty) solution based off your accurate advice. Needs to be cleaned up - but currently functioning well. – Katalpa May 12 '15 at 12:34
  • 1
    The second argument to QgsRubberBand should be a geometry type, such as QGis.Polygon. – Snorfalorpagus Jul 31 '15 at 16:03

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.