Thursday, 1 December 2016

features - How to create and remove multiple QgsRubberBands in PyQGIS?


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,,,,,,,,,,,]

Answer



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.


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...