def zoomOut(self, pos=None): if pos == None: self.setZoomFactor(self.zoom * (1.0 - self.ZOOM_WHEEL)) else: elem_ori = self.mapPosFromPos(pos) self.setZoomFactor(self.zoom * (1.0 - self.ZOOM_WHEEL)) elem_delta = elem_ori - self.mapPosFromPos(pos) self.scrollPos = QPointF(self.scrollPos) + elem_delta * self.zoom
def __init__(self, parent=None): super(PanningWebView, self).__init__() self.zoom = 1.0 self.wheel_dir = 1.0 self.setImgSize(QtCore.QSize(100, 80)) self.pressed = False self.scrolling = False self.positionMousePress = None self.scrollMousePress = None self.handIsClosed = False # self.setContextMenuPolicy(Qt.CustomContextMenu) todo fix this self.scrollPos = QPointF(0.0, 0.0) # self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True) todo fix this self.setMouseTracking(True) self.svgRenderer = QtSvg.QSvgRenderer() self.svgRenderer.setAspectRatioMode( Qt.AspectRatioMode.KeepAspectRatioByExpanding) self.svgRenderer.repaintNeeded.connect(self.update)
def paintEvent(self, ev): if not self.static_text or not self.static_text.text(): return p = QPainter(self) p.setRenderHint(QPainter.RenderHint.TextAntialiasing) # If text is too long too fit, fade it out at the end self.static_text.setTextWidth(self.rect().width()) sz = self.static_text.size() r = self.rect() p.drawStaticText(0, int(r.height() - sz.height()) // 2, self.static_text) if sz.width() > r.width(): g = QLinearGradient(QPointF(self.rect().topLeft()), QPointF(self.rect().topRight())) c = QColor(self.sb_background) c.setAlpha(0) g.setColorAt(0, c) g.setColorAt(0.8, c) g.setColorAt(1.0, self.sb_background) p.fillRect(self.rect(), QBrush(g)) p.end()
def __createMazePath(self) -> QPainterPath: cellSize = ( self.width() / self.__maze.size.x, self.height() / self.__maze.size.y, ) path = QPainterPath(QPointF(0, 0)) # draw outline of maze path.addRect( 0, 0, self.width() - 1, self.height() - 1, ) for y in range(self.__maze.size.y): currentY = y * cellSize[1] for x in range(self.__maze.size.x): currentX = x * cellSize[0] # get the list of walls surrounding this cell thisCellsWalls: Set[ AbsoluteDirection] = self.__maze.getWallsOfCellAtCoordinate( XY(x, y)) # draw north and west walls only, because the next iterations will draw the south and east walls for us (don't wanna waste paint /s) if AbsoluteDirection.west in thisCellsWalls: path.moveTo(currentX, currentY) path.lineTo(currentX, currentY + cellSize[1]) if AbsoluteDirection.north in thisCellsWalls: path.moveTo(currentX, currentY) path.lineTo(currentX + cellSize[0], currentY) return path
class PanningWebView(QWidget): ZOOM_WHEEL = 0.2 webViewScrolled = QtCore.pyqtSignal(bool) webViewResized = QtCore.pyqtSignal() def __init__(self, parent=None): super(PanningWebView, self).__init__() self.zoom = 1.0 self.wheel_dir = 1.0 self.setImgSize(QtCore.QSize(100, 80)) self.pressed = False self.scrolling = False self.positionMousePress = None self.scrollMousePress = None self.handIsClosed = False # self.setContextMenuPolicy(Qt.CustomContextMenu) todo fix this self.scrollPos = QPointF(0.0, 0.0) # self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True) todo fix this self.setMouseTracking(True) self.svgRenderer = QtSvg.QSvgRenderer() self.svgRenderer.setAspectRatioMode( Qt.AspectRatioMode.KeepAspectRatioByExpanding) self.svgRenderer.repaintNeeded.connect(self.update) def setContent(self, cnt, type): if self.scrolling: return False if not self.svgRenderer.load(cnt): logging.error("error during parse of svg data") self.setImgSize(self.svgRenderer.defaultSize()) self.svgRenderer.setFramesPerSecond(0) self.svgRenderer.setAspectRatioMode(Qt.AspectRatioMode.KeepAspectRatio) return True def setImgSize(self, newsize: QtCore.QSize): self.imgSize = newsize def resizeEvent(self, event: QResizeEvent): self.webViewResized.emit() super().resizeEvent(event) def paintEvent(self, event): if self.svgRenderer: painter = QPainter(self) rect = QtCore.QRectF( -self.scrollPos.x(), -self.scrollPos.y(), self.svgRenderer.defaultSize().width() * self.zoom, self.svgRenderer.defaultSize().height() * self.zoom, ) self.svgRenderer.render(painter, rect) def setZoomFactor(self, zoom): if zoom > 8: zoom = 8 elif zoom < 0.5: zoom = 0.5 if self.zoom != zoom: self.zoom = zoom self.webViewResized.emit() if self.imgSize.isValid(): self.setImgSize(self.imgSize) self.update() def zoomFactor(self): return self.zoom def scrollPosition(self) -> QPointF: return self.scrollPos def setScrollPosition(self, pos: QPoint): if self.scrollPos != pos: self.scrollPos = pos self.webViewResized.emit() self.update() def zoomIn(self, pos=None): if pos == None: self.setZoomFactor(self.zoomFactor() * (1.0 + self.ZOOM_WHEEL)) else: elemOri = self.mapPosFromPos(pos) self.setZoomFactor(self.zoom * (1.0 + self.ZOOM_WHEEL)) elemDelta = elemOri - self.mapPosFromPos(pos) self.scrollPos = QPointF(self.scrollPos) + elemDelta * self.zoom def zoomOut(self, pos=None): if pos == None: self.setZoomFactor(self.zoom * (1.0 - self.ZOOM_WHEEL)) else: elem_ori = self.mapPosFromPos(pos) self.setZoomFactor(self.zoom * (1.0 - self.ZOOM_WHEEL)) elem_delta = elem_ori - self.mapPosFromPos(pos) self.scrollPos = QPointF(self.scrollPos) + elem_delta * self.zoom def wheelEvent(self, event: QWheelEvent): if (self.wheel_dir * event.angleDelta().y()) < 0: self.zoomIn(event.position()) elif (self.wheel_dir * event.angleDelta().y()) > 0: self.zoomOut(event.position()) def mousePressEvent(self, mouseEvent: QMouseEvent): if (not self.pressed and not self.scrolling and mouseEvent.modifiers() == QtCore.Qt.KeyboardModifier.NoModifier): if mouseEvent.buttons() == QtCore.Qt.MouseButton.LeftButton: self.pressed = True self.scrolling = False self.handIsClosed = False QApplication.setOverrideCursor( QtCore.Qt.CursorShape.OpenHandCursor) self.scrollMousePress = self.scrollPosition() self.positionMousePress = mouseEvent.pos() def mouseReleaseEvent(self, mouseEvent: QMouseEvent): if self.scrolling: self.pressed = False self.scrolling = False self.handIsClosed = False self.positionMousePress = None QApplication.restoreOverrideCursor() self.webViewScrolled.emit(False) return if self.pressed: self.pressed = False self.scrolling = False self.handIsClosed = False QApplication.restoreOverrideCursor() return def hoveCheck(self, pos: QPointF) -> bool: return False def doubleClicked(self, pos: QPointF) -> bool: return False def mouseDoubleClickEvent(self, mouseEvent: QMouseEvent): self.doubleClicked(self.mapPosFromEvent(mouseEvent)) def mapPosFromPos(self, pos: QPointF) -> QPointF: return (pos + QPointF(self.scrollPos)) / self.zoom def mapPosFromPoint(self, mouseEvent: QPoint) -> QPoint: return (mouseEvent + QPointF(self.scrollPos)) / self.zoom def mapPosFromEvent(self, mouseEvent: QMouseEvent) -> QPointF: return (QPointF(mouseEvent.pos()) + QPointF(self.scrollPos)) / self.zoom def mouseMoveEvent(self, mouseEvent: QMouseEvent): if self.scrolling: if not self.handIsClosed: QApplication.restoreOverrideCursor() QApplication.setOverrideCursor( QtCore.Qt.CursorShape.OpenHandCursor) self.handIsClosed = True if self.scrollMousePress != None: delta = mouseEvent.pos() - self.positionMousePress self.setScrollPosition( QPoint(int(self.scrollMousePress.x()), int(self.scrollMousePress.y())) - delta) return if self.pressed: self.pressed = False self.scrolling = True self.webViewScrolled.emit(True) return if self.hoveCheck(self.mapPosFromEvent(mouseEvent)): QApplication.setOverrideCursor( QtCore.Qt.CursorShape.PointingHandCursor) else: QApplication.setOverrideCursor(QtCore.Qt.CursorShape.ArrowCursor) return
def mapPosFromEvent(self, mouseEvent: QMouseEvent) -> QPointF: return (QPointF(mouseEvent.pos()) + QPointF(self.scrollPos)) / self.zoom
def mapPosFromPoint(self, mouseEvent: QPoint) -> QPoint: return (mouseEvent + QPointF(self.scrollPos)) / self.zoom
def mapPosFromPos(self, pos: QPointF) -> QPointF: return (pos + QPointF(self.scrollPos)) / self.zoom
def generate_itemGroup(self, xs, ys, label, type): gItemGroup = QGraphicsItemGroup() pointBbx = QRectF() pointBbx.setSize(QSizeF(self.gView.labelSize, self.gView.labelSize)) textLabel = QGraphicsTextItem(label) if len(xs) == 1: pointBbx.moveCenter(QPointF(xs[0], ys[0])) textLabel.setPos(xs[0] - (textLabel.boundingRect().width() / 2), ys[0] - (textLabel.boundingRect().height() / 2)) pointShape = QGraphicsEllipseItem(pointBbx) shapeColor = Qt.GlobalColor.white textColor = Qt.GlobalColor.black tooltip = 'P{}:{}' elif len(xs) == 2: pointBbx.moveCenter(QPointF(xs[1], ys[1])) textLabel.setPos(xs[1] - (textLabel.boundingRect().width() / 2), ys[1] - (textLabel.boundingRect().height() / 2)) r, g, b = np.random.choice(range(256), size=3) line_item = QGraphicsLineItem(xs[0], ys[0], xs[1], ys[1]) line_item.setPen( QPen(QColor(r, g, b, 128), self.gView.labelSize / 6)) gItemGroup.addToGroup(line_item) # line_end = QGraphicsEllipseItem(xs[1], ys[1], # int(self.gView.labelSize/3), int(self.gView.labelSize/3)) # line_end.setPen(QPen(QColor(r, g, b), 0.5)) # line_end.setBrush(QBrush(QColor(r, g, b))) # gItemGroup.addToGroup(line_end) pointShape = QGraphicsEllipseItem(pointBbx) shapeColor = QColor(r, g, b, 128) textColor = Qt.GlobalColor.black tooltip = 'L{}:{}' # textLabel.setRotation(np.arctan((ys[1] - ys[0])/(xs[1] - xs[0]))*(180/3.14)) else: pointBbx.moveCenter(QPointF(np.mean(xs), np.mean(ys))) textLabel.setPos( np.mean(xs) - (textLabel.boundingRect().width() / 2), np.mean(ys) - (textLabel.boundingRect().height() / 2)) points = [QPointF(x, y) for x, y in zip(xs, ys)] polygon = QPolygonF(points) r, g, b = np.random.choice(range(256), size=3) zone_item = QGraphicsPolygonItem(polygon) zone_item.setPen(QPen(QColor(r, g, b), self.gView.labelSize / 10)) zone_item.setBrush(QBrush(QColor(r, g, b, 40))) gItemGroup.addToGroup(zone_item) pointShape = QGraphicsRectItem(pointBbx) shapeColor = Qt.GlobalColor.darkBlue textColor = Qt.GlobalColor.white tooltip = 'Z{}:{}' pointShape.setPen(QPen(Qt.GlobalColor.white, 0.5)) pointShape.setBrush(QBrush(shapeColor)) # self.gView.scene().addEllipse(pointBbx, QPen(Qt.white, 0.5), QBrush(Qt.black)) gItemGroup.setToolTip(tooltip.format(label, type)) gItemGroup.addToGroup(pointShape) labelFont = QFont() labelFont.setPointSize(round(self.gView.labelSize / 2)) labelFont.setBold(True) textLabel.setFont(labelFont) textLabel.setDefaultTextColor(textColor) gItemGroup.addToGroup(textLabel) return gItemGroup