class LineDrawCanvas(QWidget): def __init__(self, parent=None): super(LineDrawCanvas, self).__init__(parent) self.setMinimumSize(200, 200) self.linePen = QPen(Qt.SolidLine) self.linePen.setColor(Qt.magenta) self.linePen.setWidth(6) self.drawingPen = QPen(Qt.DashLine) self.drawingPen.setColor(Qt.cyan) self.drawingPen.setWidth(3) self.currentLine = None self.lines = [] def reset(self): self.lines = [] self.update() def paintEvent(self, event): qp = QPainter(self) qp.setPen(QPen(Qt.black)) qp.setBrush(QBrush(Qt.white)) bounds = self.rect() qp.drawRect(0, 0, bounds.width() - 1, bounds.height() - 1) # draw an outline around the graph qp.setPen(self.linePen) for line in self.lines: qp.drawLine(line) if self.currentLine != None: qp.setPen(self.drawingPen) qp.drawLine(self.currentLine) def mousePressEvent(self, event): self.currentLine = QLine(event.pos(), event.pos()) # start a new line def mouseMoveEvent(self, event): if self.currentLine != None: self.currentLine.setP2( event.pos()) # update the second point of the line self.update() # redraw the widget to show the updated line def mouseReleaseEvent(self, event): if self.currentLine != None: # Turn the currentLine into a permanent line self.lines.append(self.currentLine) self.currentLine = None self.update()
class MesOverlay(AbstractOverlay): '''Overlay for measure distances between image points ''' def __init__(self, widget): super().__init__(widget) self._started = False self._line = None self.lengthText = None def handleEvent(self, event) -> bool: trfpos = self.invertedTransform().map(event.pos()) processed = False if event.type() == QEvent.MouseButtonPress: if event.buttons() & Qt.LeftButton and not self._started: processed = True self._line = QLine(trfpos, trfpos) elif event.type() == QEvent.MouseMove: if event.buttons() & Qt.LeftButton or self._started: processed = True self._line.setP2(trfpos) elif event.type() == QEvent.MouseButtonRelease: if self._started: self.active = False if self.doneCallBack is not None: self.doneCallBack() else: self._started = True if processed: self.widget.update() return processed def render(self, painter): if self._line is None: return line = self.transform().map(self._line) pen = QPen(Qt.white) pen.setWidth(3 if self.active else 2) pen.setCapStyle(Qt.RoundCap) painter.setPen(pen) painter.drawLine(line) if self.lengthText is not None: fm = QFontMetrics(painter.font()) rc = fm.boundingRect(self.lengthText) mx = line.x1() + line.dx() / 2 - rc.center().x() my = line.y1() + line.dy() / 2 - rc.center().y() rc.translate(mx, my) rc.adjust(-5, -5, 5, 5) painter.setPen(QPen(Qt.white)) painter.fillRect(rc, Qt.black) painter.drawRect(rc) painter.drawText(rc, Qt.AlignCenter, self.lengthText) def enter(self): self.active = True self._started = False self._line = None self.lengthText = None self.widget.update() def leave(self): self.active = False self._started = False self.widget.update() def reset(self): self.active = False self._started = False self._line = None self.lengthText = None def lineLength(self): if self._line is None: return None return math.sqrt(self._line.dx()**2 + self._line.dy()**2)
class NGL_Line(NGL_Base): """ NGL_Line(NGL_Base) Provides a embedded NGL library line widget. """ # Signal used to indicate changes to the status of the widget. valueChanged = pyqtSignal(QLine) def __init__(self, parent=None): """ Constructor for ngl widget """ super(NGL_Line, self).__init__(parent) self._line = QLine(0, 0, 150, 150) self._static = True self.update() def paintEvent(self, event): """ Paint ngl widget event """ p = QPainter() p.begin(self) p.drawLine(self._line) p.end() def sizeHint(self): """ Return Qt sizeHint """ return self._size() def _size(self): width = abs(self._line.x2() - self._line.x1()) + 1 height = abs(self._line.y2() - self._line.y1()) + 1 return QSize(width, height) def update(self): self._size_update() super(NGL_Line, self).update() def _size_update(self): """ Size update for widget """ w = self._size().width() h = self._size().height() self.setMinimumSize(w, h) self.setMaximumSize(w, h) # # Provide getter and setter methods for the property. @pyqtProperty(QPoint) def P1(self): return self._line.p1() @P1.setter def P1(self, point): self._line.setP1(point) self.update() # Provide getter and setter methods for the property. @pyqtProperty(QPoint) def P2(self): return self._line.p2() @P2.setter def P2(self, point): self._line.setP2(point) self.update() def doNGLCode(self, **kwargs): template = 'NGL_GP_DrawLine({x0}, {y0}, {x1}, {y1}, {color});' # convert coordinates g = self._ngl_geometry() y1 = self._ngl_y(self.P1.y(), g.height() - 1) y2 = self._ngl_y(self.P2.y(), g.height() - 1) return template.format( x0 = g.x(), y0 = g.y() + y1, x1 = g.x() + g.width() - 1, y1 = g.y() + y2, color = self._ngl_color('color: rgb'))