3

I am developing a plugin in QGIS 3.14 to customize editing. I am drawing a line by clicking on map canvas. It is showing points with mouse click and creating a line with right click. I want to trace mouse by showing dotted line while generating points. Just like existing 'Add Line Feature' function of 'Toggle Editing' in QGIS. Following is the code which I am using now.

class StraightLine(QgsMapToolEmitPoint):
    points = []

    def __init__(self, canvas):
        # call the parent constructor
        QgsMapToolEmitPoint.__init__(self, canvas)
        # store the passed canvas
        self.canvas = canvas

        # flag to know whether the tool is performing a drawing operation 
        self.isDrawing = False
        self.dlg = CurveToolDialog()
        # create and setup the rubber band to display the line
        self.rubberBand = QgsRubberBand(iface.mapCanvas(), QgsWkbTypes.LineGeometry)  
        self.rubberBand.setColor(Qt.red)
        self.rubberBand.setWidth(1)
        self.dlg.setFocusPolicy(Qt.StrongFocus) 

    def clear(self):
        self.rubberBand.reset(False)    # False = not a polygon = a line

    def delete(self):
        self.canvas.scene().removeItem(self.rubberBand)
    
    def canvasPressEvent(self, e):
        # which the mouse button?
        if e.button() == Qt.LeftButton:
            # left click
            # if it's the first left click, clear the rubberband 
            if not self.isDrawing:
                self.clear()
                self.points = []
            # we are drawing now
            self.isDrawing = True
            point = self.toMapCoordinates(e.pos())
            # add a new point to the rubber band
            self.rubberBand.addPoint(point, True)    # True = display updates on the canvas
            self.points.append(QgsPoint(point))
            polyline = QgsGeometry.fromPolyline(self.points)
            feat = QgsFeature()
            feat.setGeometry(polyline)            
            self.rubberBand.setToGeometry(polyline)
            self.rubberBand.movePoint(point)
            self.rubberBand.show()
            # and finally show the rubber band
            self.rubberBand.show()
            
        if e.button() == Qt.RightButton:
            
            # right click, stop drawing
            self.isDrawing = False
            # emit a signal
            polyline = QgsGeometry.fromPolyline(self.points)
            feat = QgsFeature()
            feat.setGeometry(polyline)            
            self.rubberBand.setToGeometry(polyline)
            self.rubberBand.show()  
            layer = iface.activeLayer()
            f = layer.getFeature(0)
            prov1 = layer.dataProvider()
            layer.startEditing()
            prov1.addFeatures([feat])
            feat.setAttributes(f.attributes())
            layer.commitChanges()
            layer.updateExtents()
            iface.mapCanvas().refresh()  
            self.dlg.open()
           
    def geometry(self):
        return self.rubberBand.asGeometry() 

I tried adding following function which uses painter, but it doesn't make any change in working of the tool.

def mouseMoveEvent(self, event):
    if self.last:
        self.painter.drawLine(self.last, event.pos())
        self.last = event.pos()
        self.update()

1 Answer 1

0

Setting temporary rubber band different from actual rubber band helped.line style of temporary one was kept as dotted.Also, including canvasMoveEvent to draw temporary rubber band.

def canvasMoveEvent(self, event):
    if self.tempRubberBand != None and self.capturing:
        mapPt,layerPt = self.transformCoordinates(event.pos())
        self.tempRubberBand.movePoint(mapPt)

def startCapturing(self):
    color = QColor("red")
    color.setAlphaF(0.78)
    self.rubberBand = QgsRubberBand(self.canvas,QgsWkbTypes.LineGeometry)
    self.rubberBand.setWidth(2)
    self.rubberBand.setColor(color)
    self.rubberBand.show()
    self.tempRubberBand = QgsRubberBand(self.canvas,QgsWkbTypes.LineGeometry)
    self.tempRubberBand.setWidth(2)
    self.tempRubberBand.setColor(color)
    self.tempRubberBand.setLineStyle(Qt.DotLine)
    self.tempRubberBand.show()
    self.capturing = True

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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