def shape(self, object): path = QPainterPath() if (not object.cell().isEmpty()): path.addRect(self.boundingRect(object)) else: x = object.shape() if x==MapObject.Rectangle: bounds = object.bounds() if (bounds.isNull()): path.addEllipse(bounds.topLeft(), 20, 20) else: path.addRoundedRect(bounds, 10, 10) elif x==MapObject.Polygon or x==MapObject.Polyline: pos = object.position() polygon = object.polygon().translated(pos) screenPolygon = self.pixelToScreenCoords_(polygon) if (object.shape() == MapObject.Polygon): path.addPolygon(screenPolygon) else: for i in range(1, screenPolygon.size()): path.addPolygon(self.lineToPolygon(screenPolygon[i - 1], screenPolygon[i])) path.setFillRule(Qt.WindingFill) elif x==MapObject.Ellipse: bounds = object.bounds() if (bounds.isNull()): path.addEllipse(bounds.topLeft(), 20, 20) else: path.addEllipse(bounds) return path
def debug(self, painter): #Paint path painter.setBrush(QBrush(QColor(0, 0, 0, 25))) pen = QPen(QColor(255, 0, 0, 100)) pen.setWidth(1) painter.setPen(pen) #Curve area path = QPainterPath() path.addPath(self.shape()) painter.drawPath(path) #Curve controll points painter.drawEllipse(self.curvePoint1, 2, 2) painter.drawEllipse(self.curvePoint2, 2, 2) #Draw area painter.setPen(QPen(QColor(0, 255, 0, 100))) painter.setBrush(QBrush(QColor(0, 0, 0, 15))) path2 = QPainterPath() rect = self.boundingRect() path2.addRect(rect) painter.drawPath(path2) #Middel point painter.setPen(QPen(QColor(0, 0, 255, 100))) painter.drawEllipse(self.midPoint, 2, 2)
def shape(self): """ Returns the shape of this item as a QPainterPath in local coordinates. :rtype: QPainterPath """ path = QPainterPath() path.addRect(self.boundingRect()) return path
def painterPath(self): """ Returns the current shape as QPainterPath (used for collision detection). :rtype: QPainterPath """ path = QPainterPath() path.addRect(self.polygon) return path
def __init__(self, pos, edge, symbol): ''' Create the point - as a small, lightblue box ''' super(Connectionpoint, self).__init__(pos, edge=edge) path = QPainterPath() path.addRect(0, 0, 10, 10) self.setPath(path) self.setPos(pos.x() - 5, pos.y() - 5) # Symbol actually owning the connection point self.symbol = symbol
def shape(self): """ Returns the shape of this item as a QPainterPath in local coordinates. :rtype: QPainterPath """ path = QPainterPath() path.addRect(self.polygon) for shape in self.handleBound: path.addEllipse(shape) return path
def set_shape(self, width, height): ''' Compute the polygon to fit in width, height ''' path = QPainterPath() path.addRect(0, 0, width, height) path.moveTo(7, 0) path.lineTo(7, height) path.moveTo(width - 7, 0) path.lineTo(width - 7, height) self.setPath(path) super(ProcedureCall, self).set_shape(width, height)
def shape(self): """ Returns the shape of this item as a QPainterPath in local coordinates. """ path = QPainterPath() path.addRect(self.rect()) if self.isSelected(): for shape in self.handles.values(): path.addEllipse(shape) return path
def refreshPath(self): """Returns a :class:`QPainterPath` object for the minor grid lines. The path also includes a border outline and a midline for dividing scaffold and staple bases. """ bw = _BASE_WIDTH bw2 = 2 * bw part = self.part() path = QPainterPath() sub_step_size = part.subStepSize() _, canvas_size = self._model_part.getOffsetAndSize(self._id_num) # border path.addRect(0, 0, bw * canvas_size, 2 * bw) # minor tick marks for i in range(canvas_size): x = round(bw * i) if i % sub_step_size == 0: # path.moveTo(x - .5, 0) # path.lineTo(x - .5, bw2) # path.lineTo(x - .25, bw2) # path.lineTo(x - .25, 0) # path.lineTo(x, 0) # path.lineTo(x, bw2) # path.lineTo(x + .25, bw2) # path.lineTo(x + .25, 0) # path.lineTo(x + .5, 0) # path.lineTo(x + .5, bw2) # path.moveTo(x - .5, 0) # path.lineTo(x - .5, bw2) path.moveTo(x - .25, bw2) path.lineTo(x - .25, 0) path.lineTo(x, 0) path.lineTo(x, bw2) path.lineTo(x + .25, bw2) path.lineTo(x + .25, 0) # path.moveTo(x-.5, 0) # path.lineTo(x-.5, 2 * bw) # path.lineTo(x+.5, 2 * bw) # path.lineTo(x+.5, 0) else: path.moveTo(x, 0) path.lineTo(x, 2 * bw) # staple-scaffold divider path.moveTo(0, bw) path.lineTo(bw * canvas_size, bw) self.setPath(path)
def setupShapes(self): truck = QPainterPath() truck.setFillRule(Qt.WindingFill) truck.moveTo(0.0, 87.0) truck.lineTo(0.0, 60.0) truck.lineTo(10.0, 60.0) truck.lineTo(35.0, 35.0) truck.lineTo(100.0, 35.0) truck.lineTo(100.0, 87.0) truck.lineTo(0.0, 87.0) truck.moveTo(17.0, 60.0) truck.lineTo(55.0, 60.0) truck.lineTo(55.0, 40.0) truck.lineTo(37.0, 40.0) truck.lineTo(17.0, 60.0) truck.addEllipse(17.0, 75.0, 25.0, 25.0) truck.addEllipse(63.0, 75.0, 25.0, 25.0) clock = QPainterPath() clock.addEllipse(-50.0, -50.0, 100.0, 100.0) clock.addEllipse(-48.0, -48.0, 96.0, 96.0) clock.moveTo(0.0, 0.0) clock.lineTo(-2.0, -2.0) clock.lineTo(0.0, -42.0) clock.lineTo(2.0, -2.0) clock.lineTo(0.0, 0.0) clock.moveTo(0.0, 0.0) clock.lineTo(2.732, -0.732) clock.lineTo(24.495, 14.142) clock.lineTo(0.732, 2.732) clock.lineTo(0.0, 0.0) house = QPainterPath() house.moveTo(-45.0, -20.0) house.lineTo(0.0, -45.0) house.lineTo(45.0, -20.0) house.lineTo(45.0, 45.0) house.lineTo(-45.0, 45.0) house.lineTo(-45.0, -20.0) house.addRect(15.0, 5.0, 20.0, 35.0) house.addRect(-35.0, -15.0, 25.0, 25.0) text = QPainterPath() font = QFont() font.setPixelSize(50) fontBoundingRect = QFontMetrics(font).boundingRect("Qt") text.addText(-QPointF(fontBoundingRect.center()), font, "Qt") self.shapes = (clock, house, text, truck) self.shapeComboBox.activated.connect(self.shapeSelected)
def refreshPath(self): """ Returns a QPainterPath object for the minor grid lines. The path also includes a border outline and a midline for dividing scaffold and staple bases. """ bw = _BASE_WIDTH bw2 = 2 * bw part = self.part() path = QPainterPath() sub_step_size = part.subStepSize() canvas_size = part.maxBaseIdx() + 1 # border path.addRect(0, 0, bw * canvas_size, 2 * bw) # minor tick marks for i in range(canvas_size): x = round(bw * i) + .5 if i % sub_step_size == 0: path.moveTo(x - .5, 0) path.lineTo(x - .5, bw2) path.lineTo(x - .25, bw2) path.lineTo(x - .25, 0) path.lineTo(x, 0) path.lineTo(x, bw2) path.lineTo(x + .25, bw2) path.lineTo(x + .25, 0) path.lineTo(x + .5, 0) path.lineTo(x + .5, bw2) # path.moveTo(x-.5, 0) # path.lineTo(x-.5, 2 * bw) # path.lineTo(x+.5, 2 * bw) # path.lineTo(x+.5, 0) else: path.moveTo(x, 0) path.lineTo(x, 2 * bw) # staple-scaffold divider path.moveTo(0, bw) path.lineTo(bw * canvas_size, bw) self.setPath(path) if self._model_virtual_helix.scaffoldIsOnTop(): scaffoldY = 0 else: scaffoldY = bw
def painterPath(self): bw = self._BASE_WIDTH i_g = self._item_group # the childrenBoundingRect is necessary to get this to work rectIG = i_g.childrenBoundingRect() rect = self.mapRectFromItem(i_g, rectIG) if rect.width() < bw: rect.adjust(-bw / 4, 0, bw / 2, 0) path = QPainterPath() path.addRect(rect) self._item_group.setBoundingRect(rectIG) # path.addRoundedRect(rect, radius, radius) # path.moveTo(rect.right(),\ # rect.center().y()) # path.lineTo(rect.right() + radius / 2,\ # rect.center().y()) return path
def __init__(self, width, height, color, border=None): """ Initialize the icon. :type width: T <= int | float :type height: T <= int | float :type color: str :type border: str """ pixmap = QPixmap(width, height) painter = QPainter(pixmap) painter.setRenderHint(QPainter.Antialiasing) path = QPainterPath() path.addRect(QRectF(QPointF(0, 0), QPointF(width, height))) painter.fillPath(path, QBrush(QColor(color))) if border: painter.setPen(QPen(QColor(border), 0, Qt.SolidLine)) painter.drawPath(path) painter.end() super().__init__(pixmap)
def paintCorners(painter, corners, rect): # FIXME: This only works right for orthogonal maps right now hx = rect.width() / 2 hy = rect.height() / 2 x = corners if x==Corners.TopLeft: painter.drawPie(rect.translated(-hx, -hy), -90 * 16, 90 * 16) elif x==Corners.TopRight: painter.drawPie(rect.translated(hx, -hy), 180 * 16, 90 * 16) elif x==Corners.TopRight | Corners.TopLeft: painter.drawRect(rect.x(), rect.y(), rect.width(), hy) elif x==Corners.BottomLeft: painter.drawPie(rect.translated(-hx, hy), 0, 90 * 16) elif x==Corners.BottomLeft | Corners.TopLeft: painter.drawRect(rect.x(), rect.y(), hx, rect.height()) elif x==Corners.BottomLeft | Corners.TopRight: painter.drawPie(rect.translated(-hx, hy), 0, 90 * 16) painter.drawPie(rect.translated(hx, -hy), 180 * 16, 90 * 16) elif x==Corners.BottomLeft | Corners.TopRight | Corners.TopLeft: fill = QPainterPath() ellipse = QPainterPath() fill.addRect(rect) ellipse.addEllipse(rect.translated(hx, hy)) painter.drawPath(fill.subtracted(ellipse)) elif x==Corners.BottomRight: painter.drawPie(rect.translated(hx, hy), 90 * 16, 90 * 16) elif x==Corners.BottomRight | Corners.TopLeft: painter.drawPie(rect.translated(-hx, -hy), -90 * 16, 90 * 16) painter.drawPie(rect.translated(hx, hy), 90 * 16, 90 * 16) elif x==Corners.BottomRight | Corners.TopRight: painter.drawRect(rect.x() + hx, rect.y(), hx, rect.height()) elif x==Corners.BottomRight | Corners.TopRight | Corners.TopLeft: fill = QPainterPath() ellipse = QPainterPath() fill.addRect(rect) ellipse.addEllipse(rect.translated(-hx, hy)) painter.drawPath(fill.subtracted(ellipse)) elif x==Corners.BottomRight | Corners.BottomLeft: painter.drawRect(rect.x(), rect.y() + hy, rect.width(), hy) elif x==Corners.BottomRight | Corners.BottomLeft | Corners.TopLeft: fill = QPainterPath() ellipse = QPainterPath() fill.addRect(rect) ellipse.addEllipse(rect.translated(hx, -hy)) painter.drawPath(fill.subtracted(ellipse)) elif x==Corners.BottomRight | Corners.BottomLeft | Corners.TopRight: fill = QPainterPath() ellipse = QPainterPath() fill.addRect(rect) ellipse.addEllipse(rect.translated(-hx, -hy)) painter.drawPath(fill.subtracted(ellipse)) elif x==Corners.BottomRight | Corners.BottomLeft | Corners.TopRight | Corners.TopLeft: painter.drawRect(rect)
def paintWindowFrame(self, painter, option, widget): color = QColor(0, 0, 0, 64) r = self.windowFrameRect() right = QRectF(r.right(), r.top()+10, 10, r.height()-10) bottom = QRectF(r.left()+10, r.bottom(), r.width(), 10) intersectsRight = right.intersects(option.exposedRect) intersectsBottom = bottom.intersects(option.exposedRect) if intersectsRight and intersectsBottom: path = QPainterPath() path.addRect(right) path.addRect(bottom) painter.setPen(Qt.NoPen) painter.setBrush(color) painter.drawPath(path) elif intersectsBottom: painter.fillRect(bottom, color) elif intersectsRight: painter.fillRect(right, color) super(CustomProxy, self).paintWindowFrame(painter, option, widget)
def createNetPaths(self): """ Create the network pathes This method creates 2 network pathes items one for holding the occupied rectangles and one to hold the unoccupied rectangles """ # Generate 2 QPainterPath occupiedPath = QPainterPath() unoccupiedPath = QPainterPath() # For each entry in occupied matrix : # Add a rectangle to the appropriate path according the entry value for row_idx in range(self.netRows): for col_idx in range(self.netCols): if self.occupied[row_idx][col_idx]: occupiedPath.addRect(self.netRect(row_idx, col_idx)) else: unoccupiedPath.addRect(self.netRect(row_idx, col_idx)) # Create the QGraphicsPathItems that will hold the path self.createNetPath(self.occupyColor, occupiedPath, True) self.createNetPath(self.unOccupyColor, unoccupiedPath, False)
def getRoundedRectPath(self, i, yTranslation, side): path = QPainterPath(); path.setFillRule(Qt.WindingFill); path.addRoundedRect(self.ioList[i][0], self.ioList[i][1] + yTranslation, self.ioWidth, self.ioHeight, 2, 2) #Remove rounded edges on left or right side if side == 'left': path.addRect(self.ioList[i][0], self.ioList[i][1] + yTranslation, 2, 2) path.addRect(self.ioList[i][0], self.ioList[i][1] + yTranslation + self.ioHeight - 2, 2, 2) else: path.addRect(self.ioList[i][0] + self.ioWidth - 2, self.ioList[i][1] + yTranslation, 2, 2) path.addRect(self.ioList[i][0] + self.ioWidth - 2, self.ioList[i][1] + yTranslation + self.ioHeight - 2, 2, 2) return path
def paintEvent(self, event): self._alignmentPaths = [] painter = QPainter(self) painter.setPen(QColor(45, 45, 45)) circleRadius = self._circleRadius padding = self._padding rect = event.rect() size = min(rect.height(), rect.width()) offset = .5 * (rect.width() - size) painter.translate(offset, 0) borderRect = rect.__class__( rect.left() + circleRadius + padding, rect.top() + circleRadius + padding, size - 2 * (circleRadius + padding), size - 2 * (circleRadius + padding)) borderPath = QPainterPath() borderPath.addRect(*borderRect.getRect()) columnCount = 3 radioPath = QPainterPath() selectedPath = QPainterPath() for row in range(columnCount): for col in range(columnCount): index = row * columnCount + col path = QPainterPath() path.addEllipse( padding + col * .5 * borderRect.width(), padding + row * .5 * borderRect.height(), 2 * circleRadius, 2 * circleRadius) if self._alignment == index: selectedPath = path self._alignmentPaths.append(path.translated(offset, 0)) radioPath.addPath(path) painter.drawPath(borderPath - radioPath) painter.setRenderHint(QPainter.Antialiasing) painter.drawPath(radioPath) painter.fillPath(selectedPath, Qt.black)
def shape(self): """ Return real shape of the item to detect collision or hover accurately :return: QPainterPath """ # detection mouse hover on arc path path = QPainterPath() path.addPolygon(QPolygonF([self.line().p1(), self.line().p2()])) # add handles at the start and end of arc path.addRect(QRectF( self.line().p1().x() - 5, self.line().p1().y() - 5, self.line().p1().x() + 5, self.line().p1().y() + 5 )) path.addRect(QRectF( self.line().p2().x() - 5, self.line().p2().y() - 5, self.line().p2().x() + 5, self.line().p2().y() + 5 )) return path
def shape(self) -> QPainterPath: path = QPainterPath(self.path) path.addRect(self.label_rect) return path
def shape(self): path = QPainterPath() path.addRect(-10, -20, 20, 40) return path
class FileItem(QGraphicsObject): def __init__(self, fileinfo: 'FileInfo', controller: 'Controller', file_view) -> None: logger.debug("FileItem.__init__: %s", fileinfo) super().__init__() self.fileinfo = fileinfo self.controller = controller self.press_pos = None self.setFlags(QGraphicsItem.ItemIsSelectable) self.setAcceptHoverEvents(True) self.setCursor(Qt.PointingHandCursor) # self.setCacheMode(QGraphicsItem.DeviceCoordinateCache) self.file_view = file_view self._new = False self.hovering: bool = False self.animation_count = 0 self.icon = self.make_icon() self.normal_thumbnail: Thumbnail = Thumbnail("normal", self) self.large_thumbnail: Thumbnail = Thumbnail("large", self) self.metadata: Optional[Dict[str, Any]] = None self.set_tile_size(self.file_view._mode._tile_style.tile_width, self.file_view._mode._tile_style.tile_height) self.animation_timer: Optional[int] = None self._file_is_final = True self._dropable = False def on_file_modified(self, fileinfo: FileInfo, final=False): self.fileinfo = fileinfo self._file_is_final = final self._new = True if final: thumbnail = self._get_thumbnail() thumbnail.reset() def on_fileinfo_updated(self, fileinfo: FileInfo): self.fileinfo = fileinfo def set_tile_size(self, tile_width: int, tile_height: int) -> None: # the size of the base tile self.tile_rect = QRect(0, 0, tile_width, tile_height) # the size of the base tile self.thumbnail_rect = QRect(0, 0, tile_width, tile_width) # the bounding rect for drawing, it's a little bigger to allow # border effects and such self.bounding_rect = QRect(self.tile_rect.x() - 3, self.tile_rect.y() - 3, self.tile_rect.width() + 6, self.tile_rect.height() + 6) # the path used for collision detection self.qpainter_path = QPainterPath() self.qpainter_path.addRect(0, 0, tile_width, tile_height) def prepare(self) -> None: if self._file_is_final: if self.metadata is None: self.controller.request_metadata(self.fileinfo) self.metadata = {} thumbnail = self._get_thumbnail() if thumbnail.status == ThumbnailStatus.INITIAL: thumbnail.request() def paint(self, painter, option, widget) -> None: # logger.debug("FileItem.paint: %s", self.fileinfo) if not self.file_view.is_scrolling(): self.prepare() if self.animation_timer is None: # FIXME: calling os.getuid() is slow, so use 1000 as # workaround for now if self.fileinfo.uid() == 1000: bg_color = QColor(192 + 48, 192 + 48, 192 + 48) elif self.fileinfo.uid() == 0: bg_color = QColor(192 + 32, 176, 176) else: bg_color = QColor(176, 192 + 32, 176) else: bg_color = QColor(192 + 32 - 10 * self.animation_count, 192 + 32 - 10 * self.animation_count, 192 + 32 - 10 * self.animation_count) # background rectangle if True or self.animation_timer is not None: painter.fillRect(0, 0, self.tile_rect.width(), self.tile_rect.height(), bg_color) # hover rectangle if self.hovering and self.animation_timer is None: painter.fillRect( -4, -4, self.tile_rect.width() + 8, self.tile_rect.height() + 8, bg_color if self.isSelected() else QColor(192, 192, 192)) if self._dropable: painter.fillRect(0, 0, self.tile_rect.width(), self.tile_rect.height(), QColor(164, 164, 164)) renderer = FileItemRenderer(self) renderer.render(painter) def make_icon(self): icon = self.file_view.icon_from_fileinfo(self.fileinfo) return icon def hoverEnterEvent(self, ev): # logger.debug("FileItem.hoverEnterEvent: %s", self.fileinfo) self.hovering = True if not self.file_view.is_scrolling(): self.controller.show_current_filename(self.fileinfo.abspath()) self.update() def hoverLeaveEvent(self, ev): # logger.debug("FileItem.hoverLeaveEvent: %s", self.fileinfo) self.hovering = False if not self.file_view.is_scrolling(): self.controller.show_current_filename("") self.update() def set_thumbnail_image(self, image: QImage, flavor) -> None: thumbnail = self._get_thumbnail(flavor) thumbnail.set_thumbnail_image(image) self.update() def set_icon(self, icon) -> None: self.icon = icon def boundingRect(self) -> QRectF: return QRectF(self.bounding_rect) def shape(self) -> QPainterPath: return self.qpainter_path def reload(self) -> None: self.normal_thumbnail = Thumbnail("normal", self) self.large_thumbnail = Thumbnail("large", self) self.update() def reload_thumbnail(self) -> None: self.reload() def reload_metadata(self) -> None: self.metadata = None def on_click_animation(self) -> None: if self.animation_timer is not None: self.killTimer(self.animation_timer) self.animation_timer = self.startTimer(30) self.animation_count = 10 self.update() def timerEvent(self, ev) -> None: # logger.debug("FileItem.timerEvent: %s", self.fileinfo) if ev.timerId() == self.animation_timer: self.animation_count -= 1 self.update() if self.animation_count <= 0: self.killTimer(self.animation_timer) self.animation_timer = None else: assert False, "timer foobar" def _get_thumbnail(self, flavor: Optional[str] = None) -> Thumbnail: if flavor is None: flavor = self.file_view.flavor if flavor == "normal": return self.normal_thumbnail elif flavor == "large": return self.large_thumbnail else: return self.large_thumbnail def set_dropable(self, value): self._dropable = value self.update() def mousePressEvent(self, ev): if not self.shape().contains(ev.scenePos() - self.pos()): # Qt is sending events that are outside the item. This # happens when opening a context menu on an item, moving # the mouse, closing it with another click and than # clicking again. The item on which the context menu was # open gets triggered even when the click is completely # outside the item. This sems to be due to # mouseMoveEvent() getting missed while the menu is open # and Qt triggering on the mouse position before the # context menu was opened. There might be better ways to # fix this, this is just a workaround. Hover status # doesn't get updated either. ev.ignore() logger.error("FileItem.mousePressEvent: broken click ignored") return # PyQt will route the event to the child items when we don't # override this if ev.button() == Qt.LeftButton: if ev.modifiers() & Qt.ControlModifier: self.setSelected(not self.isSelected()) else: self.press_pos = ev.pos() elif ev.button() == Qt.RightButton: pass def mouseMoveEvent(self, ev): if (ev.pos() - self.press_pos).manhattanLength() > 16: # print("drag start") drag = QDrag(self.controller._gui._window) # Create the drag thumbnail if False: pix = QPixmap(self.tile_rect.width(), self.tile_rect.height()) painter = QPainter(pix) self.paint(painter, None, None) painter.end() drag.setPixmap(pix) drag.setHotSpot(ev.pos().toPoint() - self.tile_rect.topLeft()) else: pix = QPixmap( "/usr/share/icons/mate/32x32/actions/gtk-dnd-multiple.png" ).scaled(48, 48) drag.setPixmap(pix) if not self.isSelected(): self.controller.clear_selection() self.setSelected(True) mime_data = self.controller.selection_to_mimedata(uri_only=True) drag.setMimeData(mime_data) # Qt does not allow custom drag actions officially. The # default drag action value is however carried through # even if it's invalid, but cursor changes and signals # like actionChanged() misbehave. The DragWidget class is # a workaround. drag_widget = DragWidget(None) # noqa: F841 # this will eat up the mouseReleaseEvent drag.exec(Qt.CopyAction | Qt.MoveAction | Qt.LinkAction | 0x40, 0x40) def mouseReleaseEvent(self, ev): if ev.button() == Qt.LeftButton and self.press_pos is not None: self.click_action(new_window=False) elif ev.button() == Qt.MiddleButton: self.click_action(new_window=True) def click_action(self, new_window=False): self.on_click_animation() self.controller.on_click(self.fileinfo, new_window=new_window) def contextMenuEvent(self, ev): self.controller.on_item_context_menu(ev, self) def show_basename(self): pass def show_abspath(self): pass
def makePath(self): path = QPainterPath() assert len(self.points) == 2 rectangle = self.getRectFromPoints(self.points) path.addRect(rectangle) return path
def mouseMoveEvent(self, mouseEvent): """ Executed when then mouse is moved on the view. :type mouseEvent: QGraphicsSceneMouseEvent """ scene = self.scene() mousePos = mouseEvent.pos() mouseButtons = mouseEvent.buttons() viewport = self.viewport() if mouseButtons & Qt.RightButton: if (mouseEvent.pos() - self.mousePressPos).manhattanLength() >= QApplication.startDragDistance(): ######################################################################################################## # # # SCENE DRAG # # # ######################################################################################################## if scene.mode is not DiagramMode.SceneDrag: scene.setMode(DiagramMode.SceneDrag) viewport.setCursor(Qt.ClosedHandCursor) mousePos /= self.zoom mousePressPos = self.mousePressPos / self.zoom self.centerOn(self.mousePressCenterPos - mousePos + mousePressPos) else: super().mouseMoveEvent(mouseEvent) if mouseButtons & Qt.LeftButton: self.stopMove() if scene.mode is DiagramMode.RubberBandDrag: #################################################################################################### # # # RUBBERBAND DRAG # # # #################################################################################################### area = QRectF(self.mapFromScene(self.rubberBandOrigin), mousePos).normalized() path = QPainterPath() path.addRect(area) scene.setSelectionArea(self.mapToScene(path)) self.rubberBand.setGeometry(area.toRect()) if scene.mode in { DiagramMode.BreakPointMove, DiagramMode.InsertEdge, DiagramMode.MoveNode, DiagramMode.ResizeNode, DiagramMode.RubberBandDrag }: #################################################################################################### # # # VIEW SCROLLING # # # #################################################################################################### R = viewport.rect() if not R.contains(mousePos): move = QPointF(0, 0) if mousePos.x() < R.left(): move.setX(mousePos.x() - R.left()) elif mousePos.x() > R.right(): move.setX(mousePos.x() - R.right()) if mousePos.y() < R.top(): move.setY(mousePos.y() - R.top()) elif mousePos.y() > R.bottom(): move.setY(mousePos.y() - R.bottom()) if move: move.setX(clamp(move.x(), -MainView.MoveBound, +MainView.MoveBound)) move.setY(clamp(move.y(), -MainView.MoveBound, +MainView.MoveBound)) self.startMove(move, MainView.MoveRate)
def paintEvent(self, event): painter = QPainter(self) visibleRect = event.rect() columnCount = self._columnCount extra = self._cellWidthExtra cellWidth, cellHeight = self._cellWidth + 2 * extra, self._cellHeight glyphCount = len(self._glyphs) if columnCount: paintWidth = min(glyphCount, columnCount) * cellWidth else: paintWidth = 0 left = 0 top = cellHeight painter.fillRect(visibleRect, Qt.white) for index, glyph in enumerate(self._glyphs): t = top - cellHeight rect = (left, t, cellWidth, cellHeight) if visibleRect.intersects(visibleRect.__class__(*rect)): if index in self._selection: palette = self.palette() active = palette.currentColorGroup() != QPalette.Inactive opacityMultiplier = platformSpecific.colorOpacityMultiplier( ) selectionColor = palette.color(QPalette.Highlight) # TODO: alpha values somewhat arbitrary (here and in # glyphLineView) selectionColor.setAlphaF( 0.2 * opacityMultiplier if active else 0.7) painter.fillRect(QRectF(left, t, cellWidth, cellHeight), selectionColor) pixmap = self._getCurrentRepresentation(glyph) painter.drawPixmap(left, t, pixmap) # XXX: this hacks around the repr internals if (index in self._selection and cellHeight >= GlyphCellMinHeightForHeader): painter.fillRect( QRectF( left, t + cellHeight - GlyphCellHeaderHeight, cellWidth, GlyphCellHeaderHeight, ), selectionColor, ) left += cellWidth if left + cellWidth > paintWidth: left = 0 top += cellHeight # drop insertion position dropIndex = self._currentDropIndex if dropIndex is not None: if columnCount: x = (dropIndex % columnCount) * cellWidth y = (dropIndex // columnCount) * cellHeight # special-case the end-column if (dropIndex == glyphCount and glyphCount < self.width() // self._cellWidth or self.mapFromGlobal(QCursor.pos()).y() < y): x = columnCount * cellWidth y -= cellHeight else: x = y = 0 path = QPainterPath() path.addRect(x - 2, y, 3, cellHeight) path.addEllipse(x - 5, y - 5, 9, 9) path.addEllipse(x - 5, y + cellHeight - 5, 9, 9) path.setFillRule(Qt.WindingFill) pen = painter.pen() pen.setColor(Qt.white) pen.setWidth(2) painter.setPen(pen) painter.setRenderHint(QPainter.Antialiasing) painter.drawPath(path) painter.fillPath(path, insertionPositionColor)
from PyQt5.QtCore import QPointF, QRectF, Qt, QObject, pyqtSignal from PyQt5.QtGui import QBrush, QPen, QColor, QPainterPath, QPolygonF from PyQt5.QtWidgets import QGraphicsItem, QGraphicsPathItem, QGraphicsRectItem, QGraphicsEllipseItem _BASE_WIDTH = styles.PATH_BASE_WIDTH PP_L5 = QPainterPath() # Left 5' PainterPath PP_R5 = QPainterPath() # Right 5' PainterPath PP_L3 = QPainterPath() # Left 3' PainterPath PP_R3 = QPainterPath() # Right 3' PainterPath PP_53 = QPainterPath() # Left 5', Right 3' PainterPath PP_35 = QPainterPath() # Left 5', Right 3' PainterPath # set up PP_L5 (left 5' blue square) PP_L5.addRect(0.25 * _BASE_WIDTH, 0.125 * _BASE_WIDTH, 0.75 * _BASE_WIDTH, 0.75 * _BASE_WIDTH) # set up PP_R5 (right 5' blue square) PP_R5.addRect(0, 0.125 * _BASE_WIDTH, 0.75 * _BASE_WIDTH, 0.75 * _BASE_WIDTH) # set up PP_L3 (left 3' blue triangle) L3_POLY = QPolygonF() L3_POLY.append(QPointF(_BASE_WIDTH, 0)) L3_POLY.append(QPointF(0.25 * _BASE_WIDTH, 0.5 * _BASE_WIDTH)) L3_POLY.append(QPointF(_BASE_WIDTH, _BASE_WIDTH)) L3_POLY.append(QPointF(_BASE_WIDTH, 0)) PP_L3.addPolygon(L3_POLY) # set up PP_R3 (right 3' blue triangle) R3_POLY = QPolygonF() R3_POLY.append(QPointF(0, 0)) R3_POLY.append(QPointF(0.75 * _BASE_WIDTH, 0.5 * _BASE_WIDTH)) R3_POLY.append(QPointF(0, _BASE_WIDTH)) R3_POLY.append(QPointF(0, 0))
def rectanglePath(x, y, size): halfSize = size / 2 path = QPainterPath() path.addRect(x - halfSize, y - halfSize, size, size) return path
_ENAB_BRUSH = QBrush(Qt.SolidPattern) # Also for the helix number label _NO_BRUSH = QBrush(Qt.NoBrush) # _rect = QRectF(0, 0, baseWidth, baseWidth) _xScale = styles.PATH_XOVER_LINE_SCALE_X # control point x constant _yScale = styles.PATH_XOVER_LINE_SCALE_Y # control point y constant _rect = QRectF(0, 0, _BASE_WIDTH, _BASE_WIDTH) _blankRect = QRectF(0, 0, 2 * _BASE_WIDTH, _BASE_WIDTH) PPL5 = QPainterPath() # Left 5' PainterPath PPR5 = QPainterPath() # Right 5' PainterPath PPL3 = QPainterPath() # Left 3' PainterPath PPR3 = QPainterPath() # Right 3' PainterPath # set up PPL5 (left 5' blue square) PPL5.addRect(0.25 * _BASE_WIDTH, 0.125 * _BASE_WIDTH, 0.75 * _BASE_WIDTH, 0.75 * _BASE_WIDTH) # set up PPR5 (right 5' blue square) PPR5.addRect(0, 0.125 * _BASE_WIDTH, 0.75 * _BASE_WIDTH, 0.75 * _BASE_WIDTH) # set up PPL3 (left 3' blue triangle) L3_POLY = QPolygonF() L3_POLY.append(QPointF(_BASE_WIDTH, 0)) L3_POLY.append(QPointF(0.25 * _BASE_WIDTH, 0.5 * _BASE_WIDTH)) L3_POLY.append(QPointF(_BASE_WIDTH, _BASE_WIDTH)) PPL3.addPolygon(L3_POLY) # set up PPR3 (right 3' blue triangle) R3_POLY = QPolygonF() R3_POLY.append(QPointF(0, 0)) R3_POLY.append(QPointF(0.75 * _BASE_WIDTH, 0.5 * _BASE_WIDTH)) R3_POLY.append(QPointF(0, _BASE_WIDTH)) PPR3.addPolygon(R3_POLY)
def paint(self, painter, option, index): assert isinstance(painter, QPainter) if index.data(Qt.UserRole+1): if app_constants.HIGH_QUALITY_THUMBS: painter.setRenderHint(QPainter.SmoothPixmapTransform) painter.setRenderHint(QPainter.Antialiasing) gallery = index.data(Qt.UserRole+1) title = gallery.title artist = gallery.artist title_color = app_constants.GRID_VIEW_TITLE_COLOR artist_color = app_constants.GRID_VIEW_ARTIST_COLOR label_color = app_constants.GRID_VIEW_LABEL_COLOR # Enable this to see the defining box #painter.drawRect(option.rect) # define font size if 20 > len(title) > 15: title_size = "font-size:{}px;".format(self.font_size) elif 30 > len(title) > 20: title_size = "font-size:{}px;".format(self.font_size-1) elif 40 > len(title) >= 30: title_size = "font-size:{}px;".format(self.font_size-2) elif 50 > len(title) >= 40: title_size = "font-size:{}px;".format(self.font_size-3) elif len(title) >= 50: title_size = "font-size:{}px;".format(self.font_size-4) else: title_size = "font-size:{}px;".format(self.font_size) if 30 > len(artist) > 20: artist_size = "font-size:{}px;".format(self.font_size) elif 40 > len(artist) >= 30: artist_size = "font-size:{}px;".format(self.font_size-1) elif len(artist) >= 40: artist_size = "font-size:{}px;".format(self.font_size-2) else: artist_size = "font-size:{}px;".format(self.font_size) #painter.setPen(QPen(Qt.NoPen)) #option.rect = option.rect.adjusted(11, 10, 0, 0) option.rect.setWidth(self.W) option.rect.setHeight(self.H) rec = option.rect.getRect() x = rec[0] y = rec[1] w = rec[2] h = rec[3] text_area = QTextDocument() text_area.setDefaultFont(option.font) text_area.setHtml(""" <head> <style> #area {{ display:flex; width:140px; height:10px }} #title {{ position:absolute; color: {4}; font-weight:bold; {0} }} #artist {{ position:absolute; color: {5}; top:20px; right:0; {1} }} </style> </head> <body> <div id="area"> <center> <div id="title">{2} </div> <div id="artist">{3} </div> </div> </center> </body> """.format(title_size, artist_size, title, artist, title_color, artist_color)) text_area.setTextWidth(w) #chapter_area = QTextDocument() #chapter_area.setDefaultFont(option.font) #chapter_area.setHtml(""" #<font color="black">{}</font> #""".format("chapter")) #chapter_area.setTextWidth(w) def center_img(width): new_x = x if width < w: diff = w - width offset = diff//2 new_x += offset return new_x # if we can't find a cached image pix_cache = QPixmapCache.find(self.key(gallery.profile)) if isinstance(pix_cache, QPixmap): self.image = pix_cache img_x = center_img(self.image.width()) if self.image.height() < self.image.width(): #to keep aspect ratio painter.drawPixmap(QPoint(img_x,y), self.image) else: painter.drawPixmap(QPoint(img_x,y), self.image) else: self.image = QPixmap(gallery.profile) img_x = center_img(self.image.width()) QPixmapCache.insert(self.key(gallery.profile), self.image) if self.image.height() < self.image.width(): #to keep aspect ratio painter.drawPixmap(QPoint(img_x,y), self.image) else: painter.drawPixmap(QPoint(img_x,y), self.image) # draw star if it's favorited if gallery.fav == 1: painter.drawPixmap(QPointF(x,y), QPixmap(app_constants.STAR_PATH)) if app_constants._REFRESH_EXTERNAL_VIEWER: if app_constants.USE_EXTERNAL_VIEWER: self.external_icon = self.file_icons.get_external_file_icon() else: self.external_icon = self.file_icons.get_default_file_icon() if gallery.state == self.G_DOWNLOAD: painter.save() dl_box = QRect(x, y, w, 20) painter.setBrush(QBrush(QColor(0,0,0,123))) painter.setPen(QColor('white')) painter.drawRect(dl_box) painter.drawText(dl_box, Qt.AlignCenter, 'Downloading...') painter.restore() else: if app_constants.DISPLAY_GALLERY_TYPE: self.type_icon = self.file_icons.get_file_icon(gallery.path) if self.type_icon and not self.type_icon.isNull(): self.type_icon.paint(painter, QRect(x+2, y+app_constants.THUMB_H_SIZE-16, 16, 16)) if app_constants.USE_EXTERNAL_PROG_ICO: if self.external_icon and not self.external_icon.isNull(): self.external_icon.paint(painter, QRect(x+w-30, y+app_constants.THUMB_H_SIZE-28, 28, 28)) def draw_text_label(lbl_h): #draw the label for text painter.save() painter.translate(x, y+app_constants.THUMB_H_SIZE) box_color = QBrush(QColor(label_color))#QColor(0,0,0,123)) painter.setBrush(box_color) rect = QRect(0, 0, w, lbl_h) #x, y, width, height painter.fillRect(rect, box_color) painter.restore() return rect if option.state & QStyle.State_MouseOver or\ option.state & QStyle.State_Selected: title_layout = self.text_layout(title, w, self.title_font, self.title_font_m) artist_layout = self.text_layout(artist, w, self.artist_font, self.artist_font_m) t_h = title_layout.boundingRect().height() a_h = artist_layout.boundingRect().height() if app_constants.GALLERY_FONT_ELIDE: lbl_rect = draw_text_label(min(t_h+a_h+3, app_constants.GRIDBOX_LBL_H)) else: lbl_rect = draw_text_label(app_constants.GRIDBOX_LBL_H) clipping = QRectF(x, y+app_constants.THUMB_H_SIZE, w, app_constants.GRIDBOX_LBL_H - 10) title_layout.draw(painter, QPointF(x, y+app_constants.THUMB_H_SIZE), clip=clipping) artist_layout.draw(painter, QPointF(x, y+app_constants.THUMB_H_SIZE+t_h), clip=clipping) #painter.fillRect(option.rect, QColor) else: if app_constants.GALLERY_FONT_ELIDE: lbl_rect = draw_text_label(self.text_label_h) else: lbl_rect = draw_text_label(app_constants.GRIDBOX_LBL_H) # draw text painter.save() alignment = QTextOption(Qt.AlignCenter) alignment.setUseDesignMetrics(True) title_rect = QRectF(0,0,w, self.title_font_m.height()) artist_rect = QRectF(0,self.artist_font_m.height(),w, self.artist_font_m.height()) painter.translate(x, y+app_constants.THUMB_H_SIZE) if app_constants.GALLERY_FONT_ELIDE: painter.setFont(self.title_font) painter.setPen(QColor(title_color)) painter.drawText(title_rect, self.title_font_m.elidedText(title, Qt.ElideRight, w-10), alignment) painter.setPen(QColor(artist_color)) painter.setFont(self.artist_font) alignment.setWrapMode(QTextOption.NoWrap) painter.drawText(artist_rect, self.title_font_m.elidedText(artist, Qt.ElideRight, w-10), alignment) else: text_area.setDefaultFont(QFont(self.font_name)) text_area.drawContents(painter) ##painter.resetTransform() painter.restore() if option.state & QStyle.State_Selected: painter.save() selected_rect = QRectF(x, y, w, lbl_rect.height()+app_constants.THUMB_H_SIZE) painter.setPen(Qt.NoPen) painter.setBrush(QBrush(QColor(164,164,164,120))) p_path = QPainterPath() p_path.setFillRule(Qt.WindingFill) p_path.addRoundedRect(selected_rect, 5,5) p_path.addRect(x,y, 20, 20) p_path.addRect(x+w-20,y, 20, 20) painter.drawPath(p_path.simplified()) #painter.fillRect(selected_rect, QColor(164,164,164,120)) painter.restore() #if option.state & QStyle.State_Selected: # painter.setPen(QPen(option.palette.highlightedText().color())) else: super().paint(painter, option, index)
def getSymbolFromCmnd(self, symbolinfo): ''' Returns the SymbolPath for the symbol described in symbolinfo, which can either be a string or a dictionary. If symbolinfo is a string, it should be the name of a symbol that has already been defined, either as a pre-defined symbol or from a previous symbol definition. Current pre-defined symbol names are ones involving circles: 'dot': very small filled circle 'dotex': very small filled circle and outer lines of an ex mark 'dotplus': very small filled circle and outer lines of a plus mark 'circle': unfilled circle 'circfill': normal-sized filled circle 'circex': small unfilled circle and outer lines of an ex mark 'circplus': small unfilled circle and outer lines of a plus mark If symbolinfo is a dictionary, the following key/value pairs are recognized: 'name' : (string) symbol name (required) 'pts' : (sequence of pairs of floats) vertex coordinates 'fill' : (bool) color-fill symbol? If 'pts' is given, the value is coordinates that define the symbol as multiline subpaths in a [-50,50] square for typical size. The location of the point this symbol represents will be at the center of the square. A coordinate outside [-100,100] will terminate the current subpath, and the next valid coordinate will start a new subpath. This definition will replace an existing symbol with the given name. If 'pts' is not given, the symbol must already be defined, either as a pre-defined symbol (see above) or from a previous symbol definition. Raises: TypeError - if symbolinfo is neither a string nor a dictionary KeyError - if symbolinfo is a dictionary and the key 'name' is not given ValueError - if there are problems generating the symbol ''' # get the information about the symbol if isinstance(symbolinfo, str): symbol = symbolinfo pts = None fill = False elif isinstance(symbolinfo, dict): symbol = symbolinfo['name'] pts = symbolinfo.get('pts', None) fill = symbolinfo.get('fill', False) else: raise TypeError( 'symbolinfo must either be a dictionary or a string') if pts is None: # no path given; check if already defined sympath = self.__symbolpaths.get(symbol) if sympath is not None: return sympath # symbol not defined - if well known, create a SymbolPath for it if symbol == 'dot': path = QPainterPath() path.addEllipse(-10.0, -10.0, 20.0, 20.0) sympath = SymbolPath(path, True) elif symbol == 'dotplus': path = QPainterPath() path.addEllipse(-10.0, -10.0, 20.0, 20.0) # filled path, so need to draw "lines" as rectangles path.addRect(-4.0, -50.0, 8.0, 24.0) path.addRect(-4.0, 26.0, 8.0, 24.0) path.addRect(-50.0, -4.0, 24.0, 8.0) path.addRect(26.0, -4.0, 24.0, 8.0) sympath = SymbolPath(path, True) elif symbol == 'dotex': path = QPainterPath() path.addEllipse(-10.0, -10.0, 20.0, 20.0) # filled path, so need to draw "lines" as rectangles path.moveTo(-38.18, -32.53) path.lineTo(-32.53, -38.18) path.lineTo(-15.56, -21.21) path.lineTo(-21.21, -15.56) # moveTo adds an implicit closeSubpath in QPainterPath path.moveTo(-38.18, 32.53) path.lineTo(-32.53, 38.18) path.lineTo(-15.56, 21.21) path.lineTo(-21.21, 15.56) # moveTo adds an implicit closeSubpath in QPainterPath path.moveTo(38.18, -32.53) path.lineTo(32.53, -38.18) path.lineTo(15.56, -21.21) path.lineTo(21.21, -15.56) # moveTo adds an implicit closeSubpath in QPainterPath path.moveTo(38.18, 32.53) path.lineTo(32.53, 38.18) path.lineTo(15.56, 21.21) path.lineTo(21.21, 15.56) # Qt closes the subpath automatically sympath = SymbolPath(path, True) elif symbol == 'circle': path = QPainterPath() path.addEllipse(-35.0, -35.0, 70.0, 70.0) sympath = SymbolPath(path, False) elif symbol == 'circfill': path = QPainterPath() path.addEllipse(-39.0, -39.0, 78.0, 78.0) sympath = SymbolPath(path, True) elif symbol == 'circplus': path = QPainterPath() path.addEllipse(-20.0, -20.0, 40.0, 40.0) # not a filled path, so just draw the lines path.moveTo(0.0, -50.0) path.lineTo(0.0, -20.0) path.moveTo(0.0, 50.0) path.lineTo(0.0, 20.0) path.moveTo(-50.0, 0.0) path.lineTo(-20.0, 0.0) path.moveTo(50.0, 0.0) path.lineTo(20.0, 0.0) sympath = SymbolPath(path, False) elif symbol == 'circex': path = QPainterPath() path.addEllipse(-20.0, -20.0, 40.0, 40.0) # not a filled path, so just draw the lines path.moveTo(-35.35, -35.35) path.lineTo(-14.15, -14.15) path.moveTo(-35.35, 35.35) path.lineTo(-14.15, 14.15) path.moveTo(35.35, -35.35) path.lineTo(14.15, -14.15) path.moveTo(35.35, 35.35) path.lineTo(14.15, 14.15) sympath = SymbolPath(path, False) else: raise ValueError("Unknown symbol '%s'" % str(symbol)) else: # define (or redefine) a symbol from the given path try: coords = [[float(val) for val in coord] for coord in pts] if not coords: raise ValueError for crd in coords: if len(crd) != 2: raise ValueError except Exception: raise ValueError( 'pts, if given, must be a sequence of pairs of numbers') path = QPainterPath() somethingdrawn = False newstart = True for (xval, yval) in coords: # flip so positive y is up yval *= -1.0 if (xval < -100.0) or (xval > 100.0) or (yval < -100.0) or ( yval > 100.0): # end the current subpath newstart = True elif newstart: # start a new subpath; moveTo adds an implicit closeSubpath in QPainterPath path.moveTo(xval, yval) newstart = False else: # continue the current subpath path.lineTo(xval, yval) somethingdrawn = True if not somethingdrawn: del path raise ValueError( 'symbol definition does not contain any drawn lines') # Qt closes the (sub)path automatically sympath = SymbolPath(path, fill) # save and return the SymbolPath self.__symbolpaths[symbol] = sympath return sympath
def _itemsAt(self, func, obj, justOne=True): """ Go through all anchors, points and components (in this order) in the glyph, construct their canvas path and list items for which *func(path, obj)* returns True, or only return the first item if *justOne* is set to True. An item is a (contour, index) or (element, None) tuple. Point objects aren't returned directly because their usefulness is limited barring their parent contour. Here is a sample *func* function that tests whether item with path *path* contains *pos*: def myFunction(path, pos): return path.contains(pos) This is useful to find out whether an item was clicked on canvas. """ scale = self._inverseScale # TODO: export this from drawing or use QSettings. # XXX: outdated # anchor anchorSize = 7 * scale anchorHalfSize = anchorSize / 2 # offCurve offSize = 5 * scale offHalf = offSize / 2 offStrokeWidth = 2.5 * scale # onCurve onSize = 6.5 * scale onHalf = onSize / 2 onStrokeWidth = 1.5 * scale # onCurve smooth smoothSize = 8 * scale smoothHalf = smoothSize / 2 # guideline pt guidelineStrokeWidth = 1 * scale if not justOne: ret = dict( anchors=[], points=[], components=[], guidelines=[], image=None, ) if self._glyph is None: if justOne: return None return ret flags = GlyphFlags(True) # anchors if self.drawingAttribute("showGlyphAnchors", flags): for anchor in reversed(self._glyph.anchors): path = QPainterPath() path.addEllipse(anchor.x - anchorHalfSize, anchor.y - anchorHalfSize, anchorSize, anchorSize) if func(path, obj): if justOne: return anchor ret["anchors"].append(anchor) # points if self.drawingAttribute("showGlyphOnCurvePoints", flags): for contour in reversed(self._glyph): for index, point in enumerate(contour): path = QPainterPath() if point.segmentType is None: x = point.x - offHalf y = point.y - offHalf path.addEllipse(x, y, offSize, offSize) strokeWidth = offStrokeWidth else: if point.smooth: x = point.x - smoothHalf y = point.y - smoothHalf path.addEllipse(x, y, smoothSize, smoothSize) else: x = point.x - onHalf y = point.y - onHalf path.addRect(x, y, onSize, onSize) strokeWidth = onStrokeWidth path = _shapeFromPath(path, strokeWidth) if func(path, obj): if justOne: return (contour, index) ret["points"].append((contour, index)) # components for component in reversed(self._glyph.components): path = component.getRepresentation("TruFont.QPainterPath") if func(path, obj): if justOne: return component ret["components"].append(component) # guideline # TODO: we should further dispatch with showFontGuidelines, # although both are bind in the UI if self.drawingAttribute("showGlyphGuidelines", flags): for guideline in UIGlyphGuidelines(self._glyph): if None not in (guideline.x, guideline.y): # point x = guideline.x - smoothHalf y = guideline.y - smoothHalf path = QPainterPath() path.addEllipse(x, y, smoothSize, smoothSize) path = _shapeFromPath(path, guidelineStrokeWidth) if func(path, obj): if justOne: return guideline ret["guidelines"].append(guideline) # TODO: catch line if selected # image if self.drawingAttribute("showGlyphImage", flags): image = self._glyph.image pixmap = image.getRepresentation("defconQt.QPixmap") if pixmap is not None: path = QPainterPath() transform = QTransform(*image.transformation) rect = transform.mapRect(QRectF(pixmap.rect())) path.addRect(*rect.getCoords()) if func(path, obj): if justOne: return image ret["image"] = image if not justOne: return ret return None
widget: QWidget = ...): pen = QPen() pen.setCosmetic(True) pen.setColor(Qt.green) painter.setPen(pen) painter.drawPath(self.path) def boundingRect(self): return QRectF(0, 0, 640, 480) df = pd.read_pickle('../../bitmex_1m_2018.pkl') path = QPainterPath() for i in range(data_range): path.addRect(i / width, df['open'][i] / height, 10, df['open'][i] - df['close'][i]) MyGraphicsItem3 = QGraphicsPathItem(path) perf_timer("painter")(MyGraphicsItem3.paint) class MyGraphicsItem4(QGraphicsItem): def __init__(self, parent=None): QGraphicsItem.__init__(self, parent) self.setFlag(QGraphicsItem.ItemIsMovable, True) self.setFlag(QGraphicsItem.ItemIsSelectable, True) self.setFlag(QGraphicsItem.ItemIsFocusable, True) self.setAcceptHoverEvents(True) @perf_timer("painter")
def overlay_marks(self, img, is_cseed=False, calibration_sheet=False): border_color = Qt.white base_img = QImage(self.f_size.width(), self.f_size.height(), QImage.Format_ARGB32) base_img.fill(border_color) img = QImage(img) painter = QPainter() painter.begin(base_img) total_distance_h = round(base_img.width() / self.abstand_v) dist_v = round(total_distance_h) / 2 dist_h = round(total_distance_h) / 2 img = img.scaledToWidth(base_img.width() - (2 * (total_distance_h))) painter.drawImage(total_distance_h, total_distance_h, img) #frame around image pen = QPen(Qt.black, 2) painter.setPen(pen) #horz painter.drawLine(0, total_distance_h, base_img.width(), total_distance_h) painter.drawLine(0, base_img.height() - (total_distance_h), base_img.width(), base_img.height() - (total_distance_h)) #vert painter.drawLine(total_distance_h, 0, total_distance_h, base_img.height()) painter.drawLine(base_img.width() - (total_distance_h), 0, base_img.width() - (total_distance_h), base_img.height()) #border around img border_thick = 6 Rpath = QPainterPath() Rpath.addRect( QRectF((total_distance_h) + (border_thick / 2), (total_distance_h) + (border_thick / 2), base_img.width() - ((total_distance_h) * 2) - ((border_thick) - 1), (base_img.height() - ((total_distance_h)) * 2) - ((border_thick) - 1))) pen = QPen(Qt.black, border_thick) pen.setJoinStyle(Qt.MiterJoin) painter.setPen(pen) painter.drawPath(Rpath) Bpath = QPainterPath() Bpath.addRect( QRectF((total_distance_h), (total_distance_h), base_img.width() - ((total_distance_h) * 2), (base_img.height() - ((total_distance_h)) * 2))) pen = QPen(Qt.black, 1) painter.setPen(pen) painter.drawPath(Bpath) pen = QPen(Qt.black, 1) painter.setPen(pen) painter.drawLine(0, base_img.height() / 2, total_distance_h, base_img.height() / 2) painter.drawLine(base_img.width() / 2, 0, base_img.width() / 2, total_distance_h) painter.drawLine(base_img.width() - total_distance_h, base_img.height() / 2, base_img.width(), base_img.height() / 2) painter.drawLine(base_img.width() / 2, base_img.height(), base_img.width() / 2, base_img.height() - total_distance_h) #print code f_size = 37 QFontDatabase.addApplicationFont( os.path.join(os.path.dirname(__file__), 'DejaVuSansMono-Bold.ttf')) font = QFont("DejaVu Sans Mono", f_size - 11, QFont.Bold) font.setPixelSize(35) painter.setFont(font) if not calibration_sheet: if is_cseed: #its a secret painter.setPen(QPen(Qt.black, 1, Qt.DashDotDotLine)) painter.drawLine(0, dist_v, base_img.width(), dist_v) painter.drawLine(dist_h, 0, dist_h, base_img.height()) painter.drawLine(0, base_img.height() - dist_v, base_img.width(), base_img.height() - (dist_v)) painter.drawLine(base_img.width() - (dist_h), 0, base_img.width() - (dist_h), base_img.height()) painter.drawImage( ((total_distance_h)) + 11, ((total_distance_h)) + 11, QImage(icon_path('electrumb.png')).scaledToWidth( 2.1 * (total_distance_h), Qt.SmoothTransformation)) painter.setPen(QPen(Qt.white, border_thick * 8)) painter.drawLine( base_img.width() - ((total_distance_h)) - (border_thick * 8) / 2 - (border_thick / 2) - 2, (base_img.height() - ((total_distance_h))) - ((border_thick * 8) / 2) - (border_thick / 2) - 2, base_img.width() - ((total_distance_h)) - (border_thick * 8) / 2 - (border_thick / 2) - 2 - 77, (base_img.height() - ((total_distance_h))) - ((border_thick * 8) / 2) - (border_thick / 2) - 2) painter.setPen(QColor(0, 0, 0, 255)) painter.drawText( QRect( 0, base_img.height() - 107, base_img.width() - total_distance_h - border_thick - 11, base_img.height() - total_distance_h - border_thick), Qt.AlignRight, self.versioned_seed.version + '_' + self.versioned_seed.checksum) painter.end() else: # revealer painter.setPen(QPen(border_color, 17)) painter.drawLine(0, dist_v, base_img.width(), dist_v) painter.drawLine(dist_h, 0, dist_h, base_img.height()) painter.drawLine(0, base_img.height() - dist_v, base_img.width(), base_img.height() - (dist_v)) painter.drawLine(base_img.width() - (dist_h), 0, base_img.width() - (dist_h), base_img.height()) painter.setPen(QPen(Qt.black, 2)) painter.drawLine(0, dist_v, base_img.width(), dist_v) painter.drawLine(dist_h, 0, dist_h, base_img.height()) painter.drawLine(0, base_img.height() - dist_v, base_img.width(), base_img.height() - (dist_v)) painter.drawLine(base_img.width() - (dist_h), 0, base_img.width() - (dist_h), base_img.height()) logo = QImage(icon_path('revealer_c.png')).scaledToWidth( 1.3 * (total_distance_h)) painter.drawImage((total_distance_h) + (border_thick), ((total_distance_h)) + (border_thick), logo, Qt.SmoothTransformation) #frame around logo painter.setPen(QPen(Qt.black, border_thick)) painter.drawLine( total_distance_h + border_thick, total_distance_h + logo.height() + 3 * (border_thick / 2), total_distance_h + logo.width() + border_thick, total_distance_h + logo.height() + 3 * (border_thick / 2)) painter.drawLine( logo.width() + total_distance_h + 3 * (border_thick / 2), total_distance_h + (border_thick), total_distance_h + logo.width() + 3 * (border_thick / 2), total_distance_h + logo.height() + (border_thick)) #frame around code/qr qr_size = 179 painter.drawLine((base_img.width() - ((total_distance_h)) - (border_thick / 2) - 2) - qr_size, (base_img.height() - ((total_distance_h))) - ((border_thick * 8)) - (border_thick / 2) - 2, (base_img.width() / 2 + (total_distance_h / 2) - border_thick - (border_thick * 8) / 2) - qr_size, (base_img.height() - ((total_distance_h))) - ((border_thick * 8)) - (border_thick / 2) - 2) painter.drawLine( (base_img.width() / 2 + (total_distance_h / 2) - border_thick - (border_thick * 8) / 2) - qr_size, (base_img.height() - ((total_distance_h))) - ((border_thick * 8)) - (border_thick / 2) - 2, base_img.width() / 2 + (total_distance_h / 2) - border_thick - (border_thick * 8) / 2 - qr_size, ((base_img.height() - ((total_distance_h))) - (border_thick / 2) - 2)) painter.setPen(QPen(Qt.white, border_thick * 8)) painter.drawLine( base_img.width() - ((total_distance_h)) - (border_thick * 8) / 2 - (border_thick / 2) - 2, (base_img.height() - ((total_distance_h))) - ((border_thick * 8) / 2) - (border_thick / 2) - 2, base_img.width() / 2 + (total_distance_h / 2) - border_thick - qr_size, (base_img.height() - ((total_distance_h))) - ((border_thick * 8) / 2) - (border_thick / 2) - 2) painter.setPen(QColor(0, 0, 0, 255)) painter.drawText( QRect(((base_img.width() / 2) + 21) - qr_size, base_img.height() - 107, base_img.width() - total_distance_h - border_thick - 93, base_img.height() - total_distance_h - border_thick), Qt.AlignLeft, self.versioned_seed.get_ui_string_version_plus_seed()) painter.drawText( QRect( 0, base_img.height() - 107, base_img.width() - total_distance_h - border_thick - 3 - qr_size, base_img.height() - total_distance_h - border_thick), Qt.AlignRight, self.versioned_seed.checksum) # draw qr code qr_qt = self.paintQR( self.versioned_seed.get_ui_string_version_plus_seed() + self.versioned_seed.checksum) target = QRectF(base_img.width() - 65 - qr_size, base_img.height() - 65 - qr_size, qr_size, qr_size) painter.drawImage(target, qr_qt) painter.setPen(QPen(Qt.black, 4)) painter.drawLine(base_img.width() - 65 - qr_size, base_img.height() - 65 - qr_size, base_img.width() - 65 - qr_size, (base_img.height() - ((total_distance_h))) - ((border_thick * 8)) - (border_thick / 2) - 4) painter.drawLine(base_img.width() - 65 - qr_size, base_img.height() - 65 - qr_size, base_img.width() - 65, base_img.height() - 65 - qr_size) painter.end() else: # calibration only painter.end() cal_img = QImage(self.f_size.width() + 100, self.f_size.height() + 100, QImage.Format_ARGB32) cal_img.fill(Qt.white) cal_painter = QPainter() cal_painter.begin(cal_img) cal_painter.drawImage(0, 0, base_img) #black lines in the middle of border top left only cal_painter.setPen(QPen(Qt.black, 1, Qt.DashDotDotLine)) cal_painter.drawLine(0, dist_v, base_img.width(), dist_v) cal_painter.drawLine(dist_h, 0, dist_h, base_img.height()) pen = QPen(Qt.black, 2, Qt.DashDotDotLine) cal_painter.setPen(pen) n = 15 cal_painter.setFont(QFont("DejaVu Sans Mono", 21, QFont.Bold)) for x in range(-n, n): #lines on bottom (vertical calibration) cal_painter.drawLine((((base_img.width()) / (n * 2)) * (x)) + (base_img.width() / 2) - 13, x + 2 + base_img.height() - (dist_v), (((base_img.width()) / (n * 2)) * (x)) + (base_img.width() / 2) + 13, x + 2 + base_img.height() - (dist_v)) num_pos = 9 if x > 9: num_pos = 17 if x < 0: num_pos = 20 if x < -9: num_pos = 27 cal_painter.drawText((((base_img.width()) / (n * 2)) * (x)) + (base_img.width() / 2) - num_pos, 50 + base_img.height() - (dist_v), str(x)) #lines on the right (horizontal calibrations) cal_painter.drawLine( x + 2 + (base_img.width() - (dist_h)), ((base_img.height() / (2 * n)) * (x)) + (base_img.height() / n) + (base_img.height() / 2) - 13, x + 2 + (base_img.width() - (dist_h)), ((base_img.height() / (2 * n)) * (x)) + (base_img.height() / n) + (base_img.height() / 2) + 13) cal_painter.drawText(30 + (base_img.width() - (dist_h)), ((base_img.height() / (2 * n)) * (x)) + (base_img.height() / 2) + 13, str(x)) cal_painter.end() base_img = cal_img return base_img
class SortingBox(QWidget): circle_count = square_count = triangle_count = 1 def __init__(self): super(SortingBox, self).__init__() self.circlePath = QPainterPath() self.squarePath = QPainterPath() self.trianglePath = QPainterPath() self.shapeItems = [] self.previousPosition = QPoint() self.setMouseTracking(True) self.setBackgroundRole(QPalette.Base) self.itemInMotion = None self.newCircleButton = self.createToolButton( "New Circle", QIcon(":/images/circle.png"), self.createNewCircle) self.newSquareButton = self.createToolButton( "New Square", QIcon(":/images/square.png"), self.createNewSquare) self.newTriangleButton = self.createToolButton( "New Triangle", QIcon(":/images/triangle.png"), self.createNewTriangle) self.circlePath.addEllipse(0, 0, 100, 100) self.squarePath.addRect(0, 0, 100, 100) x = self.trianglePath.currentPosition().x() y = self.trianglePath.currentPosition().y() self.trianglePath.moveTo(x + 120 / 2, y) self.trianglePath.lineTo(0, 100) self.trianglePath.lineTo(120, 100) self.trianglePath.lineTo(x + 120 / 2, y) self.setWindowTitle("Tooltips") self.resize(500, 300) self.createShapeItem( self.circlePath, "Circle", self.initialItemPosition(self.circlePath), self.initialItemColor(), ) self.createShapeItem( self.squarePath, "Square", self.initialItemPosition(self.squarePath), self.initialItemColor(), ) self.createShapeItem( self.trianglePath, "Triangle", self.initialItemPosition(self.trianglePath), self.initialItemColor(), ) def event(self, event): if event.type() == QEvent.ToolTip: helpEvent = event index = self.itemAt(helpEvent.pos()) if index != -1: QToolTip.showText(helpEvent.globalPos(), self.shapeItems[index].toolTip()) else: QToolTip.hideText() event.ignore() return True return super(SortingBox, self).event(event) def resizeEvent(self, event): margin = self.style().pixelMetric(QStyle.PM_DefaultTopLevelMargin) x = self.width() - margin y = self.height() - margin y = self.updateButtonGeometry(self.newCircleButton, x, y) y = self.updateButtonGeometry(self.newSquareButton, x, y) self.updateButtonGeometry(self.newTriangleButton, x, y) def paintEvent(self, event): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) for shapeItem in self.shapeItems: painter.translate(shapeItem.position()) painter.setBrush(shapeItem.color()) painter.drawPath(shapeItem.path()) painter.translate(-shapeItem.position()) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: index = self.itemAt(event.pos()) if index != -1: self.itemInMotion = self.shapeItems[index] self.previousPosition = event.pos() value = self.shapeItems[index] del self.shapeItems[index] self.shapeItems.insert(len(self.shapeItems) - 1, value) self.update() def mouseMoveEvent(self, event): if (event.buttons() & Qt.LeftButton) and self.itemInMotion: self.moveItemTo(event.pos()) def mouseReleaseEvent(self, event): if (event.button() == Qt.LeftButton) and self.itemInMotion: self.moveItemTo(event.pos()) self.itemInMotion = None def createNewCircle(self): SortingBox.circle_count += 1 self.createShapeItem( self.circlePath, "Circle <%d>" % SortingBox.circle_count, self.randomItemPosition(), self.randomItemColor(), ) def createNewSquare(self): SortingBox.square_count += 1 self.createShapeItem( self.squarePath, "Square <%d>" % SortingBox.square_count, self.randomItemPosition(), self.randomItemColor(), ) def createNewTriangle(self): SortingBox.triangle_count += 1 self.createShapeItem( self.trianglePath, "Triangle <%d>" % SortingBox.triangle_count, self.randomItemPosition(), self.randomItemColor(), ) def itemAt(self, pos): for i in range(len(self.shapeItems) - 1, -1, -1): item = self.shapeItems[i] if item.path().contains(QPointF(pos - item.position())): return i return -1 def moveItemTo(self, pos): offset = pos - self.previousPosition self.itemInMotion.setPosition(self.itemInMotion.position() + offset) self.previousPosition = QPoint(pos) self.update() def updateButtonGeometry(self, button, x, y): size = button.sizeHint() button.setGeometry(x - size.width(), y - size.height(), size.width(), size.height()) return (y - size.height() - self.style().pixelMetric(QStyle.PM_DefaultLayoutSpacing)) def createShapeItem(self, path, toolTip, pos, color): shapeItem = ShapeItem() shapeItem.setPath(path) shapeItem.setToolTip(toolTip) shapeItem.setPosition(pos) shapeItem.setColor(color) self.shapeItems.append(shapeItem) self.update() def createToolButton(self, toolTip, icon, member): button = QToolButton(self) button.setToolTip(toolTip) button.setIcon(icon) button.setIconSize(QSize(32, 32)) button.clicked.connect(member) return button def initialItemPosition(self, path): y = (self.height() - path.controlPointRect().height()) / 2 if len(self.shapeItems) == 0: x = ((3 * self.width()) / 2 - path.controlPointRect().width()) / 2 else: x = (self.width() / len(self.shapeItems) - path.controlPointRect().width()) / 2 return QPoint(x, y) def randomItemPosition(self): x = random.randint(0, self.width() - 120) y = random.randint(0, self.height() - 120) return QPoint(x, y) def initialItemColor(self): hue = ((len(self.shapeItems) + 1) * 85) % 256 return QColor.fromHsv(hue, 255, 190) def randomItemColor(self): return QColor.fromHsv(random.randint(0, 256), 255, 190)
class MyGraphicsView(QGraphicsView): def __init__(self): QGraphicsView.__init__(self) self.setMouseTracking(True) self._dlg_file = QFileDialog() self.scene = image_scene(self) self.setScene(self.scene) # for zoom in zoom out self.unit_in = 2 self.unit_out = 1 / 2 self.imageName_ = None self.jsonName_ = None self.pixmap = None self.save_jsonName = '' self.jsonName_ = '' self.import_flag = 0 self.transform_initial = self.transform() self.zoom_flag = 0 self.setRenderHint(QPainter.Antialiasing) def import_image(self): # clear all item in view self.scene.clear() self.scene.lastpos = [] self.scene.polygon = [] self.scene.Polygon_flag = 0 self.scene.Rect_flag = 0 # import image options = self._dlg_file.Options() self.imageName_, _ = self._dlg_file.getOpenFileName(self, "Read Image", "", "Image Files (*.png *.jpg *.jpeg *.gif *.tiff *.tif);;All Files (*)", options=options) self.pixmap = QPixmap(self.imageName_) photo = QGraphicsPixmapItem(self.pixmap) # change graphic view free self.viewport().installEventFilter(self) self.setGeometry(0, 0, self.pixmap.width()+10, self.pixmap.height()+10) self.setTransform(self.transform_initial) self.scene.addItem(photo) self.import_flag = 1 def import_json(self): self.scene.clear() self.scene.lastpos = [] self.scene.polygon = [] self.scene.Polygon_flag = 0 self.scene.Rect_flag = 0 options = self._dlg_file.Options() self.jsonName_, _ = self._dlg_file.getOpenFileName(self, "Read Json", "", "Json Files (*.json);;All Files (*)", options=options) if self.jsonName_ !='': self.import_flag = 1 with open(self.jsonName_, 'r') as reader: jf = json.loads(reader.read()) # to turn string back to byte image_json = jf["image"].encode(encoding="utf-8") ba = QByteArray.fromBase64(image_json) img = QImage.fromData(ba, 'PNG') self.pixmap = QPixmap.fromImage(img) photo = QGraphicsPixmapItem(self.pixmap) self.viewport().installEventFilter(self) self.setGeometry(0, 0, self.pixmap.width() + 10, self.pixmap.height() + 10) self.scene.addItem(photo) if jf["polygon"] != []: all_poly_item = [] for i in jf["polygon"]: single_poly_item = [] for j in i: single_poly_item.append(QPointF(j[0], j[1])) all_poly_item.append(single_poly_item) # TODO: make mainwindow not only show a item, not to get this error "wrapped C/C++ object of type XXXX has been deleted" print("test") self.scene.load_polygon_item(all_poly_item) else: print("no polygon") if jf["rect"] != []: all_rect_item = [] for i in jf["rect"]: single_rect_item = [] for j in i: single_rect_item.append(QPointF(j[0], j[1])) all_rect_item.append(single_rect_item) self.scene.load_rect_item(all_rect_item) else: print("no rect") else: print("no json import") def rotate_left(self): if self.import_flag == 1: self.rotate(-10) # to get current transformation matrix for the view elif self.import_flag != 1: print("no image import") def rotate_right(self): if self.import_flag == 1: self.rotate(10) # to get current transformation matrix for the view elif self.import_flag != 1: print("no image import") def zoom_in(self): if self.import_flag == 1 and self.zoom_flag < 4: self.zoom_flag +=1 self.scale(self.unit_in, self.unit_in) elif self.import_flag != 1: print("no image import") elif self.zoom_flag == 4: print("can't zoom in") # to get current transformation matrix for the view def zoom_out(self): if self.import_flag == 1 and self.zoom_flag > -4: self.zoom_flag -= 1 self.scale(self.unit_out, self.unit_out) # to get current transformation matrix for the view elif self.import_flag != 1: print("no image import") elif self.zoom_flag == -4: print("can't zoom out") def original_view(self): if self.import_flag == 1: self.zoom_flag = 0 self.setTransform(self.transform_initial) # to get current transformation matrix for the view elif self.import_flag != 1: print("no image import") def save_image(self): options = self._dlg_file.Options() if self.pixmap is not None: # Get region of scene to capture from somewhere. area = QRectF(0, 0, self.pixmap.width() + 10, self.pixmap.height() + 10) # Create a QImage to render to and fix up a QPainter for it. image = QImage(QRectF.toRect(area).size(), QImage.Format_ARGB32_Premultiplied) painter = QPainter(image) # Render the region of interest to the QImage. self.scene.render(painter, QRectF(image.rect()), area) painter.end() save_imageName, _ = self._dlg_file.getSaveFileName(self, "Save Image", "", "Image Files (*.png *.jpg *.jpeg *.gif *.tiff *.tif);;All Files (*)", options=options) # Save the image to a file. image.save(save_imageName) else: print("can't save image") def save_json(self): options = self._dlg_file.Options() if self.pixmap is not None: area = QRectF(0, 0, self.pixmap.width() + 10, self.pixmap.height() + 10) self.select_all_scene = QPainterPath() self.select_all_scene.addRect(area) self.scene.setSelectionArea(self.select_all_scene, Qt.IntersectsItemShape, self.transform()) allitem = self.scene.items() selecteditem = self.scene.selectedItems() # selecteditem: different object has different type, use, selecteditem[?].type(), can get different object, polygon type == 5, rect type == 3, gripitem type == 2 polygon_point = [] rect_point = [] for i in selecteditem: if i.type() == 5: # get polgon item point each_point_polygon = [] for j in i.m_points: each_point_polygon.append([j.x(), j.y()]) polygon_point.append(each_point_polygon) elif i.type() == 3: each_point_rect = [] each_use = [[i.rect_point[0].x(), i.rect_point[1].x()], [i.rect_point[0].y(), i.rect_point[1].y()]] for j in i.rect_point: if j is i.rect_point[0]: each_point_rect.append([min(each_use[0]), min(each_use[1])]) else: each_point_rect.append([max(each_use[0]), max(each_use[1])]) rect_point.append(each_point_rect) # save image PIC = self.pixmap.toImage() ba = QByteArray() buffer = QBuffer(ba) buffer.open(QIODevice.WriteOnly) PIC.save(buffer, 'PNG') base64_data = ba.toBase64().data() image_data = str(base64_data, encoding='utf-8') # save to json annotation_object = { 'polygon': polygon_point, 'rect': rect_point, 'image': image_data} self.save_jsonName, _ = self._dlg_file.getSaveFileName(self, "Save Json", "", "Json Files (*.json);;All Files (*)", options=options) if self.save_jsonName != '': with open(self.save_jsonName, 'w') as json_file: json.dump(annotation_object, json_file) print("test") else: print("no choose save path") else: print("can't save json")
def paintEvent(self, event): painter = QPainter(self) visibleRect = event.rect() columnCount, rowCount = self._columnCount, self._rowCount cellWidth, cellHeight = self._cellWidth, self._cellHeight glyphCount = len(self._glyphs) if columnCount: paintHeight = math.ceil(glyphCount / columnCount) * cellHeight paintWidth = min(glyphCount, columnCount) * cellWidth else: paintHeight = paintWidth = 0 left = 0 top = cellHeight realPixel = 1 / self.devicePixelRatio() for index, glyph in enumerate(self._glyphs): t = top - cellHeight rect = (left, t, cellWidth, cellHeight) painter.fillRect(*(rect+(backgroundColor,))) if visibleRect.intersects(visibleRect.__class__(*rect)): pixmap = self._getCurrentRepresentation(glyph) painter.drawPixmap(left, t, pixmap) if index in self._selection: palette = self.palette() active = palette.currentColorGroup() != QPalette.Inactive opacityMultiplier = platformSpecific.colorOpacityMultiplier() selectionColor = palette.color(QPalette.Highlight) # TODO: alpha values somewhat arbitrary (here and in # glyphLineView) selectionColor.setAlphaF( .2 * opacityMultiplier if active else .6) pixelRatio = self.devicePixelRatio() painter.fillRect(QRectF( left + realPixel, t + realPixel, cellWidth - 3 * realPixel, cellHeight - 3 * realPixel), selectionColor) left += cellWidth if left + cellWidth > paintWidth: left = 0 top += cellHeight # h/v lines emptyCells = columnCount * rowCount - len(self._glyphs) rem = columnCount - emptyCells painter.setPen(cellGridColor) for i in range(1, self._rowCount+1): top = i * cellHeight - realPixel # don't paint on empty cells w = paintWidth - realPixel if i == self._rowCount: w -= cellWidth * emptyCells drawing.drawLine(painter, 0, top, w, top) for i in range(1, self._columnCount+1): left = i * cellWidth - realPixel # don't paint on empty cells h = paintHeight - realPixel if i > rem: h -= cellHeight drawing.drawLine(painter, left, 0, left, h) # drop insertion position dropIndex = self._currentDropIndex if dropIndex is not None: if columnCount: x = (dropIndex % columnCount) * cellWidth y = (dropIndex // columnCount) * cellHeight # special-case the end-column if dropIndex == glyphCount and \ glyphCount < self.width() // self._cellWidth or \ self.mapFromGlobal(QCursor.pos()).y() < y: x = columnCount * cellWidth y -= cellHeight else: x = y = 0 path = QPainterPath() path.addRect(x - 2, y, 3, cellHeight) path.addEllipse(x - 5, y - 5, 9, 9) path.addEllipse(x - 5, y + cellHeight - 5, 9, 9) path.setFillRule(Qt.WindingFill) pen = painter.pen() pen.setColor(Qt.white) pen.setWidth(2) painter.setPen(pen) painter.setRenderHint(QPainter.Antialiasing) painter.drawPath(path) painter.fillPath(path, insertionPositionColor)
def shape(self): # Determines the collision area path = QPainterPath() path.addRect(0, 0, self.nodeBodyWidth, self.nodeBodyHeight) return path
def paintEvent(self, event): if self.minimum() == self.maximum() == 0: return # 正弦曲线公式 y = A * sin(ωx + φ) + k # 当前值所占百分比 percent = 1 - (self.value() - self.minimum()) / \ (self.maximum() - self.minimum()) # w表示周期,6为人为定义 w = 6 * self.waterDensity * math.pi / self.width() # A振幅 高度百分比,1/26为人为定义 A = self.height() * self.waterHeight * 1 / 26 # k 高度百分比 k = self.height() * percent # 波浪1 waterPath1 = QPainterPath() waterPath1.moveTo(0, self.height()) # 起点在左下角 # 波浪2 waterPath2 = QPainterPath() waterPath2.moveTo(0, self.height()) # 起点在左下角 # 偏移 self._offset += 0.6 if self._offset > self.width() / 2: self._offset = 0 for i in range(self.width() + 1): # 从x轴开始计算y轴点 y = A * math.sin(w * i + self._offset) + k waterPath1.lineTo(i, y) # 相对第一条需要进行错位 y = A * math.sin(w * i + self._offset + self.width() / 2 * A) + k waterPath2.lineTo(i, y) # 封闭两条波浪,形成一个 U形 上面加波浪的封闭区间 waterPath1.lineTo(self.width(), self.height()) waterPath1.lineTo(0, self.height()) waterPath2.lineTo(self.width(), self.height()) waterPath2.lineTo(0, self.height()) # 整体形状(矩形或者圆形) bgPath = QPainterPath() if self.styleType: bgPath.addRect(QRectF(self.rect())) else: radius = min(self.width(), self.height()) bgPath.addRoundedRect(QRectF(self.rect()), radius, radius) # 开始画路径 painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing, True) # 设置没有画笔 painter.setPen(Qt.NoPen) # 先整体绘制背景,然后再在背景上方绘制两条波浪 painter.save() painter.setBrush(self.backgroundColor) painter.drawPath(bgPath) painter.restore() # 波浪1 painter.save() painter.setBrush(self.waterColor1) painter.drawPath(waterPath1) painter.restore() # 波浪2 painter.save() painter.setBrush(self.waterColor2) painter.drawPath(waterPath2) painter.restore() # 绘制文字 if not self.isTextVisible(): return painter.setPen(self.textColor) font = self.font() or QFont() font.setPixelSize(int(min(self.width(), self.height()) / 2)) painter.setFont(font) painter.drawText(self.rect(), Qt.AlignCenter, '%d%%' % (self.value() / self.maximum() * 100))
def paint(self, painter, option, index): assert isinstance(painter, QPainter) if index.data(Qt.UserRole+1): if app_constants.HIGH_QUALITY_THUMBS: painter.setRenderHint(QPainter.SmoothPixmapTransform) painter.setRenderHint(QPainter.Antialiasing) gallery = index.data(Qt.UserRole+1) title = gallery.title artist = gallery.artist title_color = app_constants.GRID_VIEW_TITLE_COLOR artist_color = app_constants.GRID_VIEW_ARTIST_COLOR label_color = app_constants.GRID_VIEW_LABEL_COLOR # Enable this to see the defining box #painter.drawRect(option.rect) # define font size if 20 > len(title) > 15: title_size = "font-size:{}px;".format(self.font_size) elif 30 > len(title) > 20: title_size = "font-size:{}px;".format(self.font_size-1) elif 40 > len(title) >= 30: title_size = "font-size:{}px;".format(self.font_size-2) elif 50 > len(title) >= 40: title_size = "font-size:{}px;".format(self.font_size-3) elif len(title) >= 50: title_size = "font-size:{}px;".format(self.font_size-4) else: title_size = "font-size:{}px;".format(self.font_size) if 30 > len(artist) > 20: artist_size = "font-size:{}px;".format(self.font_size) elif 40 > len(artist) >= 30: artist_size = "font-size:{}px;".format(self.font_size-1) elif len(artist) >= 40: artist_size = "font-size:{}px;".format(self.font_size-2) else: artist_size = "font-size:{}px;".format(self.font_size) #painter.setPen(QPen(Qt.NoPen)) #option.rect = option.rect.adjusted(11, 10, 0, 0) option.rect.setWidth(self.W) option.rect.setHeight(self.H) rec = option.rect.getRect() x = rec[0] y = rec[1] w = rec[2] h = rec[3] text_area = QTextDocument() text_area.setDefaultFont(option.font) text_area.setHtml(""" <head> <style> #area {{ display:flex; width:{6}px; height:{7}px }} #title {{ position:absolute; color: {4}; font-weight:bold; {0} }} #artist {{ position:absolute; color: {5}; top:20px; right:0; {1} }} </style> </head> <body> <div id="area"> <center> <div id="title">{2} </div> <div id="artist">{3} </div> </div> </center> </body> """.format(title_size, artist_size, title, artist, title_color, artist_color, 130+app_constants.SIZE_FACTOR, 1+app_constants.SIZE_FACTOR)) text_area.setTextWidth(w) #chapter_area = QTextDocument() #chapter_area.setDefaultFont(option.font) #chapter_area.setHtml(""" #<font color="black">{}</font> #""".format("chapter")) #chapter_area.setTextWidth(w) def center_img(width): new_x = x if width < w: diff = w - width offset = diff//2 new_x += offset return new_x def img_too_big(start_x): txt_layout = misc.text_layout("Image is too big!", w, self.title_font, self.title_font_m) clipping = QRectF(x, y+h//4, w, app_constants.GRIDBOX_LBL_H - 10) txt_layout.draw(painter, QPointF(x, y+h//4), clip=clipping) # if we can't find a cached image pix_cache = QPixmapCache.find(self.key(gallery.profile)) if isinstance(pix_cache, QPixmap): self.image = pix_cache img_x = center_img(self.image.width()) if self.image.width() > w or self.image.height() > h: img_too_big(img_x) else: if self.image.height() < self.image.width(): #to keep aspect ratio painter.drawPixmap(QPoint(img_x,y), self.image) else: painter.drawPixmap(QPoint(img_x,y), self.image) else: self.image = QPixmap(gallery.profile) img_x = center_img(self.image.width()) QPixmapCache.insert(self.key(gallery.profile), self.image) if self.image.width() > w or self.image.height() > h: img_too_big(img_x) else: if self.image.height() < self.image.width(): #to keep aspect ratio painter.drawPixmap(QPoint(img_x,y), self.image) else: painter.drawPixmap(QPoint(img_x,y), self.image) # draw ribbon type painter.save() painter.setPen(Qt.NoPen) if app_constants.DISPLAY_GALLERY_RIBBON: type_ribbon_w = type_ribbon_l = w*0.11 rib_top_1 = QPointF(x+w-type_ribbon_l-type_ribbon_w, y) rib_top_2 = QPointF(x+w-type_ribbon_l, y) rib_side_1 = QPointF(x+w, y+type_ribbon_l) rib_side_2 = QPointF(x+w, y+type_ribbon_l+type_ribbon_w) ribbon_polygon = QPolygonF([rib_top_1, rib_top_2, rib_side_1, rib_side_2]) ribbon_path = QPainterPath() ribbon_path.setFillRule(Qt.WindingFill) ribbon_path.addPolygon(ribbon_polygon) ribbon_path.closeSubpath() painter.setBrush(QBrush(QColor(self._ribbon_color(gallery.type)))) painter.drawPath(ribbon_path) # draw if favourited if gallery.fav == 1: star_ribbon_w = star_ribbon_l = w*0.08 rib_top_1 = QPointF(x+star_ribbon_l, y) rib_side_1 = QPointF(x, y+star_ribbon_l) rib_top_2 = QPointF(x+star_ribbon_l+star_ribbon_w, y) rib_side_2 = QPointF(x, y+star_ribbon_l+star_ribbon_w) rib_star_mid_1 = QPointF((rib_top_1.x()+rib_side_1.x())/2, (rib_top_1.y()+rib_side_1.y())/2) rib_star_factor = star_ribbon_l/4 rib_star_p1_1 = rib_star_mid_1 + QPointF(rib_star_factor, -rib_star_factor) rib_star_p1_2 = rib_star_p1_1 + QPointF(-rib_star_factor, -rib_star_factor) rib_star_p1_3 = rib_star_mid_1 + QPointF(-rib_star_factor, rib_star_factor) rib_star_p1_4 = rib_star_p1_3 + QPointF(-rib_star_factor, -rib_star_factor) crown_1 = QPolygonF([rib_star_p1_1, rib_star_p1_2, rib_star_mid_1, rib_star_p1_4, rib_star_p1_3]) painter.setBrush(QBrush(QColor("yellow"))) painter.drawPolygon(crown_1) ribbon_polygon = QPolygonF([rib_top_1, rib_side_1, rib_side_2, rib_top_2]) ribbon_path = QPainterPath() ribbon_path.setFillRule(Qt.WindingFill) ribbon_path.addPolygon(ribbon_polygon) ribbon_path.closeSubpath() painter.drawPath(ribbon_path) #painter.setPen(QColor("#d35400")) #painter.drawPolyline(rib_top_1, rib_star_p1_1, rib_star_p1_2, rib_star_mid_1, rib_star_p1_4, rib_star_p1_3, rib_side_1) #painter.drawLine(rib_top_1, rib_top_2) #painter.drawLine(rib_top_2, rib_side_2) #painter.drawLine(rib_side_1, rib_side_2) painter.restore() if app_constants._REFRESH_EXTERNAL_VIEWER: if app_constants.USE_EXTERNAL_VIEWER: self.external_icon = self.file_icons.get_external_file_icon() else: self.external_icon = self.file_icons.get_default_file_icon() if gallery.state == self.G_DOWNLOAD: painter.save() dl_box = QRect(x, y, w, 20) painter.setBrush(QBrush(QColor(0,0,0,123))) painter.setPen(QColor('white')) painter.drawRect(dl_box) painter.drawText(dl_box, Qt.AlignCenter, 'Downloading...') painter.restore() else: if app_constants.DISPLAY_GALLERY_TYPE: self.type_icon = self.file_icons.get_file_icon(gallery.path) if self.type_icon and not self.type_icon.isNull(): self.type_icon.paint(painter, QRect(x+2, y+app_constants.THUMB_H_SIZE-16, 16, 16)) if app_constants.USE_EXTERNAL_PROG_ICO: if self.external_icon and not self.external_icon.isNull(): self.external_icon.paint(painter, QRect(x+w-30, y+app_constants.THUMB_H_SIZE-28, 28, 28)) def draw_text_label(lbl_h): #draw the label for text painter.save() painter.translate(x, y+app_constants.THUMB_H_SIZE) box_color = QBrush(QColor(label_color))#QColor(0,0,0,123)) painter.setBrush(box_color) rect = QRect(0, 0, w, lbl_h) #x, y, width, height painter.fillRect(rect, box_color) painter.restore() return rect if option.state & QStyle.State_MouseOver or\ option.state & QStyle.State_Selected: title_layout = misc.text_layout(title, w, self.title_font, self.title_font_m) artist_layout = misc.text_layout(artist, w, self.artist_font, self.artist_font_m) t_h = title_layout.boundingRect().height() a_h = artist_layout.boundingRect().height() if app_constants.GALLERY_FONT_ELIDE: lbl_rect = draw_text_label(min(t_h+a_h+3, app_constants.GRIDBOX_LBL_H)) else: lbl_rect = draw_text_label(app_constants.GRIDBOX_LBL_H) clipping = QRectF(x, y+app_constants.THUMB_H_SIZE, w, app_constants.GRIDBOX_LBL_H - 10) painter.setPen(QColor(title_color)) title_layout.draw(painter, QPointF(x, y+app_constants.THUMB_H_SIZE), clip=clipping) painter.setPen(QColor(artist_color)) artist_layout.draw(painter, QPointF(x, y+app_constants.THUMB_H_SIZE+t_h), clip=clipping) #painter.fillRect(option.rect, QColor) else: if app_constants.GALLERY_FONT_ELIDE: lbl_rect = draw_text_label(self.text_label_h) else: lbl_rect = draw_text_label(app_constants.GRIDBOX_LBL_H) # draw text painter.save() alignment = QTextOption(Qt.AlignCenter) alignment.setUseDesignMetrics(True) title_rect = QRectF(0,0,w, self.title_font_m.height()) artist_rect = QRectF(0,self.artist_font_m.height(),w, self.artist_font_m.height()) painter.translate(x, y+app_constants.THUMB_H_SIZE) if app_constants.GALLERY_FONT_ELIDE: painter.setFont(self.title_font) painter.setPen(QColor(title_color)) painter.drawText(title_rect, self.title_font_m.elidedText(title, Qt.ElideRight, w-10), alignment) painter.setPen(QColor(artist_color)) painter.setFont(self.artist_font) alignment.setWrapMode(QTextOption.NoWrap) painter.drawText(artist_rect, self.title_font_m.elidedText(artist, Qt.ElideRight, w-10), alignment) else: text_area.setDefaultFont(QFont(self.font_name)) text_area.drawContents(painter) ##painter.resetTransform() painter.restore() if option.state & QStyle.State_Selected: painter.save() selected_rect = QRectF(x, y, w, lbl_rect.height()+app_constants.THUMB_H_SIZE) painter.setPen(Qt.NoPen) painter.setBrush(QBrush(QColor(164,164,164,120))) painter.drawRoundedRect(selected_rect, 5, 5) #painter.fillRect(selected_rect, QColor(164,164,164,120)) painter.restore() if gallery.dead_link: painter.save() selected_rect = QRectF(x, y, w, lbl_rect.height()+app_constants.THUMB_H_SIZE) painter.setPen(Qt.NoPen) painter.setBrush(QBrush(QColor(255,0,0,120))) p_path = QPainterPath() p_path.setFillRule(Qt.WindingFill) p_path.addRoundedRect(selected_rect, 5,5) p_path.addRect(x,y, 20, 20) p_path.addRect(x+w-20,y, 20, 20) painter.drawPath(p_path.simplified()) painter.setPen(QColor("white")) txt_layout = misc.text_layout("Cannot find gallery source!", w, self.title_font, self.title_font_m) txt_layout.draw(painter, QPointF(x, y+h*0.3)) painter.restore() if app_constants.DEBUG: painter.save() painter.setBrush(QBrush(QColor("red"))) painter.setPen(QColor("white")) txt_l = self.title_font_m.width(str(gallery.id)) painter.drawRect(x, y+40, txt_l*2, self.title_font_m.height()) painter.drawText(x+1, y+51, str(gallery.id)) painter.restore() if option.state & QStyle.State_Selected: painter.setPen(QPen(option.palette.highlightedText().color())) else: super().paint(painter, option, index)
def initUI(self): pg.setConfigOption('background', 'w') self.actual_dir = os.getcwd() self.lblTit = pg.LabelItem(justify='right') # self.lblTit.setText("Hola") #Variables self.data_dir = '' self.result_dir = '' self.nom_dir = [] self.nom_arch = [] self.nom_facil = [] self.sizes = np.asarray([120, 60, 30, 15, 7.5, 3.75, 1.875, 0.9375]) buttons = QHBoxLayout() datos = QVBoxLayout() contain = QSplitter(Qt.Horizontal) ima = QVBoxLayout() self.glw = pg.GraphicsLayoutWidget(border=(100, 100, 100)) self.glw.useOpenGL(True) self.glw.addItem(self.lblTit, col=1, colspan=4) self.glw.nextRow() self.glw.addLabel('Canales', angle=-90, rowspan=3) vtick = QPainterPath() vtick.moveTo(0, -0.5) vtick.lineTo(0, 0.5) vtick.addRect(0, 0.5, 1, 1) s1 = pg.ScatterPlotItem(pxMode=False) s1.setSymbol(vtick) s1.setSize(1) s2 = pg.ScatterPlotItem(pxMode=False) s2.setSymbol(vtick) s2.setSize(1) s3 = pg.ScatterPlotItem(pxMode=False) s3.setSymbol(vtick) s3.setSize(1) # s3.setPen=(QColor(*np.random.randint(0, 255 + 1, 3).tolist())) s4 = pg.ScatterPlotItem(pxMode=False) s4.setSymbol(vtick) s4.setSize(1) s5 = pg.ScatterPlotItem(pxMode=False) s5.setSymbol(vtick) s5.setSize(1) s6 = pg.ScatterPlotItem(pxMode=False) s6.setSymbol(vtick) s6.setSize(1) s7 = pg.ScatterPlotItem(pxMode=False) s7.setSymbol(vtick) s7.setSize(1) s8 = pg.ScatterPlotItem(pxMode=False) s8.setSymbol(vtick) s8.setSize(1) s9 = pg.ScatterPlotItem(pxMode=False) s9.setSymbol(vtick) s9.setSize(1) s10 = pg.ScatterPlotItem(pxMode=False) s10.setSymbol(vtick) s10.setSize(1) s11 = pg.ScatterPlotItem(pxMode=False) s11.setSymbol(vtick) s11.setSize(1) s12 = pg.ScatterPlotItem(pxMode=False) s12.setSymbol(vtick) s12.setSize(1) s13 = pg.ScatterPlotItem(pxMode=False) s13.setSymbol(vtick) s13.setSize(1) s14 = pg.ScatterPlotItem(pxMode=False) s14.setSymbol(vtick) s14.setSize(1) s15 = pg.ScatterPlotItem(pxMode=False) s15.setSymbol(vtick) s15.setSize(1) s16 = pg.ScatterPlotItem(pxMode=False) s16.setSymbol(vtick) s16.setSize(1) s17 = pg.ScatterPlotItem(pxMode=False) s17.setSymbol(vtick) s17.setSize(1) s18 = pg.ScatterPlotItem(pxMode=False) s18.setSymbol(vtick) s18.setSize(1) s19 = pg.ScatterPlotItem(pxMode=False) s19.setSymbol(vtick) s19.setSize(1) s20 = pg.ScatterPlotItem(pxMode=False) s20.setSymbol(vtick) s20.setSize(1) s21 = pg.ScatterPlotItem(pxMode=False) s21.setSymbol(vtick) s21.setSize(1) s22 = pg.ScatterPlotItem(pxMode=False) s22.setSymbol(vtick) s22.setSize(1) y = [ '0', 'EMG', 'ROG', 'LOG', 'T6', 'T5', 'T4', 'T3', 'PZ', 'P4', 'P3', 'O2', 'O1', 'FZ', 'FP2', 'FP1', 'F8', 'F7', 'F4', 'F3', 'CZ', 'C4', 'C3' ] ydict = dict(enumerate(y)) stringaxis = pg.AxisItem(orientation='left') stringaxis.setTicks([ydict.items()]) self.p1 = self.glw.addPlot(axisItems={'left': stringaxis}, row=1, col=1) # self.p2 = self.glw.addPlot(col=0) # self.p1.setYRange(-0.5, 26.5, padding=0) self.p1.setLimits(yMin=-0.5) self.p1.setLimits(yMax=26.5) self.p1.addItem(s1) self.p1.addItem(s2) self.p1.addItem(s3) self.p1.addItem(s4) self.p1.addItem(s5) self.p1.addItem(s6) self.p1.addItem(s7) self.p1.addItem(s8) self.p1.addItem(s9) self.p1.addItem(s10) self.p1.addItem(s11) self.p1.addItem(s12) self.p1.addItem(s13) self.p1.addItem(s14) self.p1.addItem(s15) self.p1.addItem(s16) self.p1.addItem(s17) self.p1.addItem(s18) self.p1.addItem(s19) self.p1.addItem(s20) self.p1.addItem(s21) self.p1.addItem(s22) self.spis = [ s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22 ] self.lytEpoch = QFormLayout() self.cmbEpoch = QComboBox() self.cmbEpoch.addItem("120") self.cmbEpoch.addItem("60") self.cmbEpoch.addItem("30") self.cmbEpoch.addItem("15") self.cmbEpoch.addItem("7.5") self.cmbEpoch.addItem("3.75") self.cmbEpoch.addItem("1.875") self.cmbEpoch.addItem("0.9375") self.lytEpoch.addRow("Epoch size: ", self.cmbEpoch) btn_data_dir = QPushButton('Load Files') btn_data_dir.clicked.connect(lambda: self.openFiles(1)) btn_result_dir = QPushButton('Save Results') btn_result_dir.clicked.connect(lambda: self.openFiles(2)) btn_do = QPushButton('Do') btn_do.clicked.connect(self.llenarTabla) self.table = QTableWidget() btn_make = QPushButton('Processing') btn_make.clicked.connect(self.showDialog) btn_showSujeto = QPushButton('Sujeto') btn_showSujeto.clicked.connect(self.recuperaSujeto) datos.addLayout(self.lytEpoch) buttons.addWidget(btn_data_dir) buttons.addWidget(btn_result_dir) buttons.addWidget(btn_do) datos.addLayout(buttons) datos.addWidget(self.table) datos.addWidget(btn_make) datos.addWidget(btn_showSujeto) ima.addWidget(self.glw) bot = QWidget() bot.setLayout(datos) gra = QWidget() gra.setLayout(ima) contain.addWidget(bot) contain.addWidget(gra) self.addWidget(contain)
def _itemsAt(self, func, obj, justOne=True): """ Go through all anchors, points and components (in this order) in the glyph, construct their canvas path and list items for which *func(path, obj)* returns True, or only return the first item if *justOne* is set to True. An item is a (point, contour) or (anchor, None) or (component, None) tuple. The second argument permits accessing parent contour to post notifications. Here is a sample *func* function that tests whether item with path *path* contains *pos*: def myFunction(path, pos): return path.contains(pos) This is useful to find out whether an item was clicked on canvas. """ scale = self._inverseScale # TODO: export this from drawing or use QSettings. # anchor anchorSize = 6 * scale anchorHalfSize = anchorSize / 2 # offCurve offWidth = 5 * scale offHalf = offWidth / 2.0 # onCurve onWidth = 7 * scale onHalf = onWidth / 2.0 # onCurve smooth smoothWidth = 8 * scale smoothHalf = smoothWidth / 2.0 if not justOne: ret = dict( anchors=[], contours=[], points=[], components=[], ) for anchor in reversed(self._glyph.anchors): path = QPainterPath() path.addEllipse(anchor.x - anchorHalfSize, anchor.y - anchorHalfSize, anchorSize, anchorSize) if func(path, obj): if justOne: return (anchor, None) ret["anchors"].append(anchor) for contour in reversed(self._glyph): for point in contour: path = QPainterPath() if point.segmentType is None: x = point.x - offHalf y = point.y - offHalf path.addEllipse(x, y, offWidth, offWidth) elif point.smooth: x = point.x - smoothHalf y = point.y - smoothHalf path.addEllipse(x, y, smoothWidth, smoothWidth) else: x = point.x - onHalf y = point.y - onHalf path.addRect(x, y, onWidth, onWidth) if func(path, obj): if justOne: return (point, contour) ret["contours"].append(contour) ret["points"].append(point) for component in reversed(self._glyph.components): path = component.getRepresentation("defconQt.QPainterPath") if func(path, obj): if justOne: return (component, None) ret["components"].append(component) if not justOne: return ret return None
def paintEvent(self, event): super(WaterFloatButton, self).paintEvent(event) painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing, True) # 鼠标悬浮进度 edge_color = QColor(self.hover_bg) pro = 0 if self.hover_progress > 0 or self.press_progress or len( self.waters) > 0: if self.water_animation: ''' 不用判断 water 是出现还是消失状态 如果一直悬浮的话,颜色不会变 而如果是点一下立马移开,文字会出现一种“渐隐渐现”的效果 ''' if len(self.waters) > 0: pro = max(self.hover_progress, self.waters[-1].progress) else: pro = self.hover_progress else: math.max(self.hover_progress, self.press_progress) edge_color.setAlpha(255 * (100 - pro) / 100) # 画边框 path = QPainterPath() if self.show_foreground: path = self.getBgPainterPath() # 整体背景 # 出现动画 if self.show_ani_appearing and self.show_ani_progress != 100 and self.border_bg.alpha( ) != 0: pw = self.size().width() * self.show_ani_progress / 100 rect = QRect(0, 0, pw, self.size().height()) rect_path = QPainterPath() rect_path.addRect(rect) path &= rect_path x = self.show_ani_point.x() y = self.show_ani_point.y() gen = self.quick_sqrt(x * x + y * y) x = -self.water_self.radius * x / gen # 动画起始中心点横坐标 反向 y = -self.water_self.radius * y / gen # 动画起始中心点纵坐标 反向 if self.border_bg.alpha() != 0: # 如果有背景,则不进行画背景线条 painter.setPen(self.border_bg) painter.drawPath(path) # 画文字 if (self.self_enabled or self.fore_enabled) and self.text != '': rect = QRect(QPoint(0, 0), self.size()) color: QColor if pro: if self.auto_text_color: aim_color = QColor(0, 0, 0) if self.isLightColor( self.hover_bg) else QColor(255, 255, 255) color = QColor( self.text_color.red() + (aim_color.red() - self.text_color.red()) * pro / 100, self.text_color.green() + (aim_color.green() - self.text_color.green()) * pro / 100, self.text_color.blue() + (aim_color.blue() - self.text_color.blue()) * pro / 100, 255) painter.setPen(color) else: color = self.text_color color.setAlpha(255) painter.setPen(color) if self.font_size > 0: font = painter.font() font.setPixelSize(self.font_size) painter.setFont(font) painter.drawText(rect, Qt.AlignCenter, self.text)
def paint(self, painter, option, widget): painter.save() painter.setRenderHint(QPainter.Antialiasing, bool(options.antialiasing == ANTIALIASING_FULL)) selected = self.isSelected() theme = canvas.theme if self.m_port_type == PORT_TYPE_AUDIO_JACK: poly_color = theme.port_audio_jack_bg_sel if selected else theme.port_audio_jack_bg poly_pen = theme.port_audio_jack_pen_sel if selected else theme.port_audio_jack_pen text_pen = theme.port_audio_jack_text_sel if selected else theme.port_audio_jack_text conn_pen = QPen(theme.port_audio_jack_pen_sel) elif self.m_port_type == PORT_TYPE_MIDI_JACK: poly_color = theme.port_midi_jack_bg_sel if selected else theme.port_midi_jack_bg poly_pen = theme.port_midi_jack_pen_sel if selected else theme.port_midi_jack_pen text_pen = theme.port_midi_jack_text_sel if selected else theme.port_midi_jack_text conn_pen = QPen(theme.port_midi_jack_pen_sel) elif self.m_port_type == PORT_TYPE_MIDI_ALSA: poly_color = theme.port_midi_alsa_bg_sel if selected else theme.port_midi_alsa_bg poly_pen = theme.port_midi_alsa_pen_sel if selected else theme.port_midi_alsa_pen text_pen = theme.port_midi_alsa_text_sel if selected else theme.port_midi_alsa_text conn_pen = QPen(theme.port_midi_alsa_pen_sel) elif self.m_port_type == PORT_TYPE_PARAMETER: poly_color = theme.port_parameter_bg_sel if selected else theme.port_parameter_bg poly_pen = theme.port_parameter_pen_sel if selected else theme.port_parameter_pen text_pen = theme.port_parameter_text_sel if selected else theme.port_parameter_text conn_pen = QPen(theme.port_parameter_pen_sel) else: qCritical( "PatchCanvas::CanvasPort.paint() - invalid port type '%s'" % port_type2str(self.m_port_type)) return # To prevent quality worsening poly_pen = QPen(poly_pen) poly_pen.setWidthF(poly_pen.widthF() + 0.00001) if self.m_is_alternate: poly_color = poly_color.darker(180) #poly_pen.setColor(poly_pen.color().darker(110)) #text_pen.setColor(text_pen.color()) #.darker(150)) #conn_pen.setColor(conn_pen.color()) #.darker(150)) lineHinting = poly_pen.widthF() / 2 poly_locx = [0, 0, 0, 0, 0] poly_corner_xhinting = (float(canvas.theme.port_height) / 2) % floor( float(canvas.theme.port_height) / 2) if poly_corner_xhinting == 0: poly_corner_xhinting = 0.5 * ( 1 - 7 / (float(canvas.theme.port_height) / 2)) if self.m_port_mode == PORT_MODE_INPUT: text_pos = QPointF(3, canvas.theme.port_text_ypos) if canvas.theme.port_mode == Theme.THEME_PORT_POLYGON: poly_locx[0] = lineHinting poly_locx[1] = self.m_port_width + 5 - lineHinting poly_locx[2] = self.m_port_width + 12 - poly_corner_xhinting poly_locx[3] = self.m_port_width + 5 - lineHinting poly_locx[4] = lineHinting elif canvas.theme.port_mode == Theme.THEME_PORT_SQUARE: poly_locx[0] = lineHinting poly_locx[1] = self.m_port_width + 5 - lineHinting poly_locx[2] = self.m_port_width + 5 - lineHinting poly_locx[3] = self.m_port_width + 5 - lineHinting poly_locx[4] = lineHinting else: qCritical( "PatchCanvas::CanvasPort.paint() - invalid theme port mode '%s'" % canvas.theme.port_mode) return elif self.m_port_mode == PORT_MODE_OUTPUT: text_pos = QPointF(9, canvas.theme.port_text_ypos) if canvas.theme.port_mode == Theme.THEME_PORT_POLYGON: poly_locx[0] = self.m_port_width + 12 - lineHinting poly_locx[1] = 7 + lineHinting poly_locx[2] = 0 + poly_corner_xhinting poly_locx[3] = 7 + lineHinting poly_locx[4] = self.m_port_width + 12 - lineHinting elif canvas.theme.port_mode == Theme.THEME_PORT_SQUARE: poly_locx[0] = self.m_port_width + 12 - lineHinting poly_locx[1] = 5 + lineHinting poly_locx[2] = 5 + lineHinting poly_locx[3] = 5 + lineHinting poly_locx[4] = self.m_port_width + 12 - lineHinting else: qCritical( "PatchCanvas::CanvasPort.paint() - invalid theme port mode '%s'" % canvas.theme.port_mode) return else: qCritical( "PatchCanvas::CanvasPort.paint() - invalid port mode '%s'" % port_mode2str(self.m_port_mode)) return polygon = QPolygonF() polygon += QPointF(poly_locx[0], lineHinting) polygon += QPointF(poly_locx[1], lineHinting) polygon += QPointF(poly_locx[2], float(canvas.theme.port_height) / 2) polygon += QPointF(poly_locx[3], canvas.theme.port_height - lineHinting) polygon += QPointF(poly_locx[4], canvas.theme.port_height - lineHinting) polygon += QPointF(poly_locx[0], lineHinting) if canvas.theme.port_bg_pixmap: portRect = polygon.boundingRect().adjusted(-lineHinting + 1, -lineHinting + 1, lineHinting - 1, lineHinting - 1) portPos = portRect.topLeft() painter.drawTiledPixmap(portRect, canvas.theme.port_bg_pixmap, portPos) else: painter.setBrush(poly_color) #.lighter(200)) painter.setPen(poly_pen) painter.drawPolygon(polygon) painter.setPen(text_pen) painter.setFont(self.m_port_font) painter.drawText(text_pos, self.m_port_name) if canvas.theme.idx == Theme.THEME_OOSTUDIO and canvas.theme.port_bg_pixmap: conn_pen.setCosmetic(True) conn_pen.setWidthF(0.4) painter.setPen(conn_pen) if self.m_port_mode == PORT_MODE_INPUT: connLineX = portRect.left() + 1 else: connLineX = portRect.right() - 1 conn_path = QPainterPath() conn_path.addRect( QRectF(connLineX - 1, portRect.top(), 2, portRect.height())) painter.fillPath(conn_path, conn_pen.brush()) painter.drawLine( QLineF(connLineX, portRect.top(), connLineX, portRect.bottom())) painter.restore()
_ENAB_BRUSH = QBrush(Qt.SolidPattern) # Also for the helix number label _NO_BRUSH = QBrush(Qt.NoBrush) # _rect = QRectF(0, 0, baseWidth, baseWidth) _xScale = styles.PATH_XOVER_LINE_SCALE_X # control point x constant _yScale = styles.PATH_XOVER_LINE_SCALE_Y # control point y constant _rect = QRectF(0, 0, _BASE_WIDTH, _BASE_WIDTH) _blankRect = QRectF(0, 0, 2*_BASE_WIDTH, _BASE_WIDTH) PPL5 = QPainterPath() # Left 5' PainterPath PPR5 = QPainterPath() # Right 5' PainterPath PPL3 = QPainterPath() # Left 3' PainterPath PPR3 = QPainterPath() # Right 3' PainterPath # set up PPL5 (left 5' blue square) PPL5.addRect(0.25*_BASE_WIDTH, 0.125*_BASE_WIDTH, 0.75*_BASE_WIDTH, 0.75*_BASE_WIDTH) # set up PPR5 (right 5' blue square) PPR5.addRect(0, 0.125*_BASE_WIDTH, 0.75*_BASE_WIDTH, 0.75*_BASE_WIDTH) # set up PPL3 (left 3' blue triangle) L3_POLY = QPolygonF() L3_POLY.append(QPointF(_BASE_WIDTH, 0)) L3_POLY.append(QPointF(0.25*_BASE_WIDTH, 0.5*_BASE_WIDTH)) L3_POLY.append(QPointF(_BASE_WIDTH, _BASE_WIDTH)) PPL3.addPolygon(L3_POLY) # set up PPR3 (right 3' blue triangle) R3_POLY = QPolygonF() R3_POLY.append(QPointF(0, 0)) R3_POLY.append(QPointF(0.75*_BASE_WIDTH, 0.5*_BASE_WIDTH)) R3_POLY.append(QPointF(0, _BASE_WIDTH)) PPR3.addPolygon(R3_POLY)
def _itemsAt(self, func, obj, justOne=True): """ Go through all anchors, points and components (in this order) in the glyph, construct their canvas path and list items for which *func(path, obj)* returns True, or only return the first item if *justOne* is set to True. An item is a (point, contour) or (anchor, None) or (component, None) tuple. The second argument permits accessing parent contour to post notifications. Here is a sample *func* function that tests whether item with path *path* contains *pos*: def myFunction(path, pos): return path.contains(pos) This is useful to find out whether an item was clicked on canvas. """ scale = self._inverseScale # TODO: export this from drawing or use QSettings. # anchor anchorSize = 6 * scale anchorHalfSize = anchorSize / 2 # offCurve offWidth = 5 * scale offHalf = offWidth / 2 offStrokeWidth = 3 * scale # onCurve onWidth = 7 * scale onHalf = onWidth / 2 onStrokeWidth = 1.5 * scale # onCurve smooth smoothWidth = 8 * scale smoothHalf = smoothWidth / 2 # guideline pt guidelineStrokeWidth = 1 * scale if not justOne: ret = dict( anchors=[], contours=[], points=[], components=[], guidelines=[], image=None, ) # anchors for anchor in reversed(self._glyph.anchors): path = QPainterPath() path.addEllipse(anchor.x - anchorHalfSize, anchor.y - anchorHalfSize, anchorSize, anchorSize) if func(path, obj): if justOne: return (anchor, None) ret["anchors"].append(anchor) # points for contour in reversed(self._glyph): for point in contour: path = QPainterPath() if point.segmentType is None: x = point.x - offHalf y = point.y - offHalf path.addEllipse(x, y, offWidth, offWidth) strokeWidth = offStrokeWidth else: if point.smooth: x = point.x - smoothHalf y = point.y - smoothHalf path.addEllipse(x, y, smoothWidth, smoothWidth) else: x = point.x - onHalf y = point.y - onHalf path.addRect(x, y, onWidth, onWidth) strokeWidth = onStrokeWidth path = _shapeFromPath(path, strokeWidth) if func(path, obj): if justOne: return (point, contour) ret["contours"].append(contour) ret["points"].append(point) # components for component in reversed(self._glyph.components): path = component.getRepresentation("TruFont.QPainterPath") if func(path, obj): if justOne: return (component, None) ret["components"].append(component) # guideline for guideline in UIGlyphGuidelines(self._glyph): if None not in (guideline.x, guideline.y): # point x = guideline.x - smoothHalf y = guideline.y - smoothHalf path = QPainterPath() path.addEllipse(x, y, smoothWidth, smoothWidth) path = _shapeFromPath(path, guidelineStrokeWidth) if func(path, obj): if justOne: return (guideline, None) ret["guidelines"].append(guideline) # TODO: catch line if selected # image image = self._glyph.image pixmap = image.getRepresentation("defconQt.QPixmap") if pixmap is not None: path = QPainterPath() transform = QTransform(*image.transformation) rect = transform.mapRect(QRectF(pixmap.rect())) path.addRect(*rect.getCoords()) if func(path, obj): if justOne: return (image, None) ret["image"] = image if not justOne: return ret return None
class GripItem(QGraphicsPathItem): # circle = QPainterPath() # circle.addEllipse(QRectF(-5, -5, 10, 10)) # square = QPainterPath() # square.addRect(QRectF(-5, -5, 10, 10)) def __init__(self, annotation_item, index, grip_props): """ grip the item and show the properties QRectF(x, y, width, height) grip_props={ grip_ellipse_size: 6, grip_square_size: 3, grip_ellipse_color: grip_square_color: } :param annotation_item: :param index: :param grip_props: grip properties from the PolygonAnnotation """ super(GripItem, self).__init__() self.name = "polygon_selector" self.ellipse_size = grip_props["grip_ellipse_size"] self.square_size = grip_props["grip_square_size"] self.ellipse_color = grip_props["grip_ellipse_color"] self.square_color = grip_props["grip_square_color"] self.ellipse_width = grip_props["grip_ellipse_width"] self.square_width = grip_props["grip_square_width"] self.grip_hover_color = grip_props["grip_hover_color"] self.circle = QPainterPath() self.circle.addEllipse(QRectF(-self.ellipse_size / 2, -self.ellipse_size / 2, self.ellipse_size, self.ellipse_size)) self.square = QPainterPath() self.square.addRect(QRectF(-self.square_size / 2, -self.square_size / 2, self.square_size, self.square_size)) self.m_annotation_item = annotation_item self.m_index = index # self.setPath(GripItem.circle) self.setPath(self.circle) self.setBrush(self.ellipse_color) self.setPen(QPen(self.ellipse_color, self.ellipse_width)) self.setFlag(QGraphicsItem.ItemIsSelectable, True) self.setFlag(QGraphicsItem.ItemIsMovable, True) self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True) self.setAcceptHoverEvents(True) self.setZValue(11) self.setCursor(QCursor(Qt.PointingHandCursor)) def hoverEnterEvent(self, event): # self.setPath(GripItem.square) self.setPath(self.square) self.setBrush(self.square_color) super(GripItem, self).hoverEnterEvent(event) def hoverLeaveEvent(self, event): # self.setPath(GripItem.circle) self.setPath(self.circle) self.setBrush(self.grip_hover_color) # self.setBrush(QColor("green")) super(GripItem, self).hoverLeaveEvent(event) def mouseReleaseEvent(self, event): self.setSelected(False) super(GripItem, self).mouseReleaseEvent(event) def itemChange(self, change, value): if change == QGraphicsItem.ItemPositionChange and self.isEnabled(): self.m_annotation_item.movePoint(self.m_index, value) return super(GripItem, self).itemChange(change, value)
from PyQt5.QtCore import QPointF, QRectF, Qt, QObject, pyqtSignal from PyQt5.QtGui import QBrush, QPen, QColor, QPainterPath, QPolygonF from PyQt5.QtWidgets import QGraphicsItem, QGraphicsPathItem, QGraphicsRectItem, QGraphicsEllipseItem _BASE_WIDTH = styles.PATH_BASE_WIDTH PP_L5 = QPainterPath() # Left 5' PainterPath PP_R5 = QPainterPath() # Right 5' PainterPath PP_L3 = QPainterPath() # Left 3' PainterPath PP_R3 = QPainterPath() # Right 3' PainterPath PP_53 = QPainterPath() # Left 5', Right 3' PainterPath PP_35 = QPainterPath() # Left 5', Right 3' PainterPath # set up PP_L5 (left 5' blue square) PP_L5.addRect(0.25 * _BASE_WIDTH, 0.125 * _BASE_WIDTH, 0.75 * _BASE_WIDTH, 0.75 * _BASE_WIDTH) # set up PP_R5 (right 5' blue square) PP_R5.addRect(0, 0.125 * _BASE_WIDTH, 0.75 * _BASE_WIDTH, 0.75 * _BASE_WIDTH) # set up PP_L3 (left 3' blue triangle) L3_POLY = QPolygonF() L3_POLY.append(QPointF(_BASE_WIDTH, 0)) L3_POLY.append(QPointF(0.25 * _BASE_WIDTH, 0.5 * _BASE_WIDTH)) L3_POLY.append(QPointF(_BASE_WIDTH, _BASE_WIDTH)) L3_POLY.append(QPointF(_BASE_WIDTH, 0)) PP_L3.addPolygon(L3_POLY) # set up PP_R3 (right 3' blue triangle) R3_POLY = QPolygonF() R3_POLY.append(QPointF(0, 0)) R3_POLY.append(QPointF(0.75 * _BASE_WIDTH, 0.5 * _BASE_WIDTH)) R3_POLY.append(QPointF(0, _BASE_WIDTH))
def shape(self): path = QPainterPath() path.addRect(self.rect) return path
def shape(self): path = QPainterPath() path.addRect(self.bounding_rect) return path
def handleShapeDescription(self, shape, list, textOnly=False): if (shape.type() != "KoSvgTextShapeID" and textOnly is True): return shapeDesc = {} shapeDesc["name"] = shape.name() rect = shape.boundingBox() listOfPoints = [ rect.topLeft(), rect.topRight(), rect.bottomRight(), rect.bottomLeft() ] shapeDoc = minidom.parseString(shape.toSvg()) docElem = shapeDoc.documentElement svgRegExp = re.compile('[MLCSQHVATmlzcqshva]\d+\.?\d* \d+\.?\d*') transform = docElem.getAttribute("transform") coord = [] adjust = QTransform() # TODO: If we get global transform api, use that instead of parsing manually. if "translate" in transform: transform = transform.replace('translate(', '') for c in transform[:-1].split(" "): coord.append(float(c)) if len(coord) < 2: coord.append(coord[0]) adjust = QTransform(1, 0, 0, 1, coord[0], coord[1]) if "matrix" in transform: transform = transform.replace('matrix(', '') for c in transform[:-1].split(" "): coord.append(float(c)) adjust = QTransform(coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]) path = QPainterPath() if docElem.localName == "path": dVal = docElem.getAttribute("d") listOfSvgStrings = [" "] listOfSvgStrings = svgRegExp.findall(dVal) if listOfSvgStrings: listOfPoints = [] for l in listOfSvgStrings: line = l[1:] coordinates = line.split(" ") if len(coordinates) < 2: coordinates.append(coordinates[0]) x = float(coordinates[-2]) y = float(coordinates[-1]) offset = QPointF() if l.islower(): offset = listOfPoints[0] if l.lower().startswith("m"): path.moveTo(QPointF(x, y) + offset) elif l.lower().startswith("h"): y = listOfPoints[-1].y() path.lineTo(QPointF(x, y) + offset) elif l.lower().startswith("v"): x = listOfPoints[-1].x() path.lineTo(QPointF(x, y) + offset) elif l.lower().startswith("c"): path.cubicTo(coordinates[0], coordinates[1], coordinates[2], coordinates[3], x, y) else: path.lineTo(QPointF(x, y) + offset) path.setFillRule(Qt.WindingFill) for polygon in path.simplified().toSubpathPolygons(adjust): for point in polygon: listOfPoints.append(point) elif docElem.localName == "rect": listOfPoints = [] if (docElem.hasAttribute("x")): x = float(docElem.getAttribute("x")) else: x = 0 if (docElem.hasAttribute("y")): y = float(docElem.getAttribute("y")) else: y = 0 w = float(docElem.getAttribute("width")) h = float(docElem.getAttribute("height")) path.addRect(QRectF(x, y, w, h)) for point in path.toFillPolygon(adjust): listOfPoints.append(point) elif docElem.localName == "ellipse": listOfPoints = [] if (docElem.hasAttribute("cx")): x = float(docElem.getAttribute("cx")) else: x = 0 if (docElem.hasAttribute("cy")): y = float(docElem.getAttribute("cy")) else: y = 0 ry = float(docElem.getAttribute("ry")) rx = float(docElem.getAttribute("rx")) path.addEllipse(QPointF(x, y), rx, ry) for point in path.toFillPolygon(adjust): listOfPoints.append(point) elif docElem.localName == "text": # NOTE: This only works for horizontal preformated text. Vertical text needs a different # ordering of the rects, and wraparound should try to take the shape it is wrapped in. family = "sans-serif" if docElem.hasAttribute("font-family"): family = docElem.getAttribute("font-family") size = "11" if docElem.hasAttribute("font-size"): size = docElem.getAttribute("font-size") multilineText = True for el in docElem.childNodes: if el.nodeType == minidom.Node.TEXT_NODE: multilineText = False if multilineText: listOfPoints = [] listOfRects = [] # First we collect all the possible line-rects. for el in docElem.childNodes: if docElem.hasAttribute("font-family"): family = docElem.getAttribute("font-family") if docElem.hasAttribute("font-size"): size = docElem.getAttribute("font-size") fontsize = int(size) font = QFont(family, fontsize) string = el.toxml() string = re.sub("\<.*?\>", " ", string) string = string.replace(" ", " ") width = min( QFontMetrics(font).width(string.strip()), rect.width()) height = QFontMetrics(font).height() anchor = "start" if docElem.hasAttribute("text-anchor"): anchor = docElem.getAttribute("text-anchor") top = rect.top() if len(listOfRects) > 0: top = listOfRects[-1].bottom() if anchor == "start": spanRect = QRectF(rect.left(), top, width, height) listOfRects.append(spanRect) elif anchor == "end": spanRect = QRectF(rect.right() - width, top, width, height) listOfRects.append(spanRect) else: # Middle spanRect = QRectF(rect.center().x() - (width * 0.5), top, width, height) listOfRects.append(spanRect) # Now we have all the rects, we can check each and draw a # polygon around them. heightAdjust = ( rect.height() - (listOfRects[-1].bottom() - rect.top())) / len(listOfRects) for i in range(len(listOfRects)): span = listOfRects[i] addtionalHeight = i * heightAdjust if i == 0: listOfPoints.append(span.topLeft()) listOfPoints.append(span.topRight()) else: if listOfRects[i - 1].width() < span.width(): listOfPoints.append( QPointF(span.right(), span.top() + addtionalHeight)) listOfPoints.insert( 0, QPointF(span.left(), span.top() + addtionalHeight)) else: bottom = listOfRects[i - 1].bottom( ) + addtionalHeight - heightAdjust listOfPoints.append( QPointF(listOfRects[i - 1].right(), bottom)) listOfPoints.insert( 0, QPointF(listOfRects[i - 1].left(), bottom)) listOfPoints.append(QPointF(span.right(), rect.bottom())) listOfPoints.insert(0, QPointF(span.left(), rect.bottom())) path = QPainterPath() path.moveTo(listOfPoints[0]) for p in range(1, len(listOfPoints)): path.lineTo(listOfPoints[p]) path.closeSubpath() listOfPoints = [] for point in path.toFillPolygon(adjust): listOfPoints.append(point) shapeDesc["boundingBox"] = listOfPoints if (shape.type() == "KoSvgTextShapeID" and textOnly is True): shapeDesc["text"] = shape.toSvg() list.append(shapeDesc)
def shape(self): path = QPainterPath() path.addRect(14, 14, 82, 42) return path
def overlay_marks(self, img, is_cseed=False, calibration_sheet=False): border_color = Qt.white base_img = QImage(self.f_size.width(),self.f_size.height(), QImage.Format_ARGB32) base_img.fill(border_color) img = QImage(img) painter = QPainter() painter.begin(base_img) total_distance_h = round(base_img.width() / self.abstand_v) dist_v = round(total_distance_h) / 2 dist_h = round(total_distance_h) / 2 img = img.scaledToWidth(base_img.width() - (2 * (total_distance_h))) painter.drawImage(total_distance_h, total_distance_h, img) #frame around image pen = QPen(Qt.black, 2) painter.setPen(pen) #horz painter.drawLine(0, total_distance_h, base_img.width(), total_distance_h) painter.drawLine(0, base_img.height()-(total_distance_h), base_img.width(), base_img.height()-(total_distance_h)) #vert painter.drawLine(total_distance_h, 0, total_distance_h, base_img.height()) painter.drawLine(base_img.width()-(total_distance_h), 0, base_img.width()-(total_distance_h), base_img.height()) #border around img border_thick = 6 Rpath = QPainterPath() Rpath.addRect(QRectF((total_distance_h)+(border_thick/2), (total_distance_h)+(border_thick/2), base_img.width()-((total_distance_h)*2)-((border_thick)-1), (base_img.height()-((total_distance_h))*2)-((border_thick)-1))) pen = QPen(Qt.black, border_thick) pen.setJoinStyle (Qt.MiterJoin) painter.setPen(pen) painter.drawPath(Rpath) Bpath = QPainterPath() Bpath.addRect(QRectF((total_distance_h), (total_distance_h), base_img.width()-((total_distance_h)*2), (base_img.height()-((total_distance_h))*2))) pen = QPen(Qt.black, 1) painter.setPen(pen) painter.drawPath(Bpath) pen = QPen(Qt.black, 1) painter.setPen(pen) painter.drawLine(0, base_img.height()/2, total_distance_h, base_img.height()/2) painter.drawLine(base_img.width()/2, 0, base_img.width()/2, total_distance_h) painter.drawLine(base_img.width()-total_distance_h, base_img.height()/2, base_img.width(), base_img.height()/2) painter.drawLine(base_img.width()/2, base_img.height(), base_img.width()/2, base_img.height() - total_distance_h) #print code f_size = 37 QFontDatabase.addApplicationFont(os.path.join(os.path.dirname(__file__), 'DejaVuSansMono-Bold.ttf')) font = QFont("DejaVu Sans Mono", f_size-11, QFont.Bold) font.setPixelSize(35) painter.setFont(font) if not calibration_sheet: if is_cseed: #its a secret painter.setPen(QPen(Qt.black, 1, Qt.DashDotDotLine)) painter.drawLine(0, dist_v, base_img.width(), dist_v) painter.drawLine(dist_h, 0, dist_h, base_img.height()) painter.drawLine(0, base_img.height()-dist_v, base_img.width(), base_img.height()-(dist_v)) painter.drawLine(base_img.width()-(dist_h), 0, base_img.width()-(dist_h), base_img.height()) painter.drawImage(((total_distance_h))+11, ((total_distance_h))+11, QImage(icon_path('electrumb.png')).scaledToWidth(2.1*(total_distance_h), Qt.SmoothTransformation)) painter.setPen(QPen(Qt.white, border_thick*8)) painter.drawLine(base_img.width()-((total_distance_h))-(border_thick*8)/2-(border_thick/2)-2, (base_img.height()-((total_distance_h)))-((border_thick*8)/2)-(border_thick/2)-2, base_img.width()-((total_distance_h))-(border_thick*8)/2-(border_thick/2)-2 - 77, (base_img.height()-((total_distance_h)))-((border_thick*8)/2)-(border_thick/2)-2) painter.setPen(QColor(0,0,0,255)) painter.drawText(QRect(0, base_img.height()-107, base_img.width()-total_distance_h - border_thick - 11, base_img.height()-total_distance_h - border_thick), Qt.AlignRight, self.versioned_seed.version + '_'+self.versioned_seed.checksum) painter.end() else: # revealer painter.setPen(QPen(border_color, 17)) painter.drawLine(0, dist_v, base_img.width(), dist_v) painter.drawLine(dist_h, 0, dist_h, base_img.height()) painter.drawLine(0, base_img.height()-dist_v, base_img.width(), base_img.height()-(dist_v)) painter.drawLine(base_img.width()-(dist_h), 0, base_img.width()-(dist_h), base_img.height()) painter.setPen(QPen(Qt.black, 2)) painter.drawLine(0, dist_v, base_img.width(), dist_v) painter.drawLine(dist_h, 0, dist_h, base_img.height()) painter.drawLine(0, base_img.height()-dist_v, base_img.width(), base_img.height()-(dist_v)) painter.drawLine(base_img.width()-(dist_h), 0, base_img.width()-(dist_h), base_img.height()) logo = QImage(icon_path('revealer_c.png')).scaledToWidth(1.3*(total_distance_h)) painter.drawImage((total_distance_h)+ (border_thick), ((total_distance_h))+ (border_thick), logo, Qt.SmoothTransformation) #frame around logo painter.setPen(QPen(Qt.black, border_thick)) painter.drawLine(total_distance_h+border_thick, total_distance_h+logo.height()+3*(border_thick/2), total_distance_h+logo.width()+border_thick, total_distance_h+logo.height()+3*(border_thick/2)) painter.drawLine(logo.width()+total_distance_h+3*(border_thick/2), total_distance_h+(border_thick), total_distance_h+logo.width()+3*(border_thick/2), total_distance_h+logo.height()+(border_thick)) #frame around code/qr qr_size = 179 painter.drawLine((base_img.width()-((total_distance_h))-(border_thick/2)-2)-qr_size, (base_img.height()-((total_distance_h)))-((border_thick*8))-(border_thick/2)-2, (base_img.width()/2+(total_distance_h/2)-border_thick-(border_thick*8)/2)-qr_size, (base_img.height()-((total_distance_h)))-((border_thick*8))-(border_thick/2)-2) painter.drawLine((base_img.width()/2+(total_distance_h/2)-border_thick-(border_thick*8)/2)-qr_size, (base_img.height()-((total_distance_h)))-((border_thick*8))-(border_thick/2)-2, base_img.width()/2 + (total_distance_h/2)-border_thick-(border_thick*8)/2-qr_size, ((base_img.height()-((total_distance_h)))-(border_thick/2)-2)) painter.setPen(QPen(Qt.white, border_thick * 8)) painter.drawLine( base_img.width() - ((total_distance_h)) - (border_thick * 8) / 2 - (border_thick / 2) - 2, (base_img.height() - ((total_distance_h))) - ((border_thick * 8) / 2) - (border_thick / 2) - 2, base_img.width() / 2 + (total_distance_h / 2) - border_thick - qr_size, (base_img.height() - ((total_distance_h))) - ((border_thick * 8) / 2) - (border_thick / 2) - 2) painter.setPen(QColor(0,0,0,255)) painter.drawText(QRect(((base_img.width()/2) +21)-qr_size, base_img.height()-107, base_img.width()-total_distance_h - border_thick -93, base_img.height()-total_distance_h - border_thick), Qt.AlignLeft, self.versioned_seed.get_ui_string_version_plus_seed()) painter.drawText(QRect(0, base_img.height()-107, base_img.width()-total_distance_h - border_thick -3 -qr_size, base_img.height()-total_distance_h - border_thick), Qt.AlignRight, self.versioned_seed.checksum) # draw qr code qr_qt = self.paintQR(self.versioned_seed.get_ui_string_version_plus_seed() + self.versioned_seed.checksum) target = QRectF(base_img.width()-65-qr_size, base_img.height()-65-qr_size, qr_size, qr_size ) painter.drawImage(target, qr_qt) painter.setPen(QPen(Qt.black, 4)) painter.drawLine(base_img.width()-65-qr_size, base_img.height()-65-qr_size, base_img.width() - 65 - qr_size, (base_img.height() - ((total_distance_h))) - ((border_thick * 8)) - (border_thick / 2) - 4 ) painter.drawLine(base_img.width()-65-qr_size, base_img.height()-65-qr_size, base_img.width() - 65, base_img.height()-65-qr_size ) painter.end() else: # calibration only painter.end() cal_img = QImage(self.f_size.width() + 100, self.f_size.height() + 100, QImage.Format_ARGB32) cal_img.fill(Qt.white) cal_painter = QPainter() cal_painter.begin(cal_img) cal_painter.drawImage(0,0, base_img) #black lines in the middle of border top left only cal_painter.setPen(QPen(Qt.black, 1, Qt.DashDotDotLine)) cal_painter.drawLine(0, dist_v, base_img.width(), dist_v) cal_painter.drawLine(dist_h, 0, dist_h, base_img.height()) pen = QPen(Qt.black, 2, Qt.DashDotDotLine) cal_painter.setPen(pen) n=15 cal_painter.setFont(QFont("DejaVu Sans Mono", 21, QFont.Bold)) for x in range(-n,n): #lines on bottom (vertical calibration) cal_painter.drawLine((((base_img.width())/(n*2)) *(x))+ (base_img.width()/2)-13, x+2+base_img.height()-(dist_v), (((base_img.width())/(n*2)) *(x))+ (base_img.width()/2)+13, x+2+base_img.height()-(dist_v)) num_pos = 9 if x > 9 : num_pos = 17 if x < 0 : num_pos = 20 if x < -9: num_pos = 27 cal_painter.drawText((((base_img.width())/(n*2)) *(x))+ (base_img.width()/2)-num_pos, 50+base_img.height()-(dist_v), str(x)) #lines on the right (horizontal calibrations) cal_painter.drawLine(x+2+(base_img.width()-(dist_h)), ((base_img.height()/(2*n)) *(x))+ (base_img.height()/n)+(base_img.height()/2)-13, x+2+(base_img.width()-(dist_h)), ((base_img.height()/(2*n)) *(x))+ (base_img.height()/n)+(base_img.height()/2)+13) cal_painter.drawText(30+(base_img.width()-(dist_h)), ((base_img.height()/(2*n)) *(x))+ (base_img.height()/2)+13, str(x)) cal_painter.end() base_img = cal_img return base_img
def drawGlyphPoints( painter, glyph, scale, rect, drawStartPoints=True, drawOnCurves=True, drawOffCurves=True, drawCoordinates=False, drawSelection=True, onCurveColor=None, otherColor=None, backgroundColor=None): if onCurveColor is None: layer = glyph.layer if layer is not None and layer.color is not None: onCurveColor = colorToQColor(layer.color) else: onCurveColor = defaultColor("glyphOnCurvePoints") if otherColor is None: otherColor = defaultColor("glyphOtherPoints") if backgroundColor is None: backgroundColor = defaultColor("background") # get the outline data outlineData = glyph.getRepresentation("defconQt.OutlineInformation") points = [] # start points if drawStartPoints and outlineData["startPoints"]: startWidth = startHeight = 15 * scale startHalf = startWidth / 2.0 path = QPainterPath() for point, angle in outlineData["startPoints"]: x, y = point if angle is not None: path.moveTo(x, y) path.arcTo(x - startHalf, y - startHalf, startWidth, startHeight, 180 - angle, 180) path.closeSubpath() else: path.addEllipse( x - startHalf, y - startHalf, startWidth, startHeight) startPointColor = QColor(otherColor) aF = startPointColor.alphaF() startPointColor.setAlphaF(aF * .3) painter.fillPath(path, startPointColor) # handles if drawOffCurves and outlineData["offCurvePoints"]: painter.save() painter.setPen(otherColor) for pt1, pt2 in outlineData["bezierHandles"]: x1, y1 = pt1 x2, y2 = pt2 # TODO: should lineWidth account scale by default drawLine(painter, x1, y1, x2, y2, 1.0 * scale) painter.restore() # on curve if drawOnCurves and outlineData["onCurvePoints"]: width = 7 * scale half = width / 2.0 smoothWidth = 8 * scale smoothHalf = smoothWidth / 2.0 painter.save() path = QPainterPath() selectedPath = QPainterPath() for point in outlineData["onCurvePoints"]: x, y = point["point"] points.append((x, y)) pointPath = QPainterPath() if point["smooth"]: x -= smoothHalf y -= smoothHalf pointPath.addEllipse(x, y, smoothWidth, smoothWidth) else: x -= half y -= half pointPath.addRect(x, y, width, width) if drawSelection and point["selected"]: selectedPath.addPath(pointPath) path.addPath(pointPath) pen = QPen(onCurveColor) pen.setWidthF(1.5 * scale) painter.setPen(pen) painter.fillPath(selectedPath, onCurveColor) painter.drawPath(path) painter.restore() # off curve if drawOffCurves and outlineData["offCurvePoints"]: # lines # points offWidth = 5 * scale offHalf = offWidth / 2.0 path = QPainterPath() selectedPath = QPainterPath() for point in outlineData["offCurvePoints"]: x, y = point["point"] points.append((x, y)) pointPath = QPainterPath() x -= offHalf y -= offHalf pointPath.addEllipse(x, y, offWidth, offWidth) if drawSelection and point["selected"]: selectedPath.addPath(pointPath) else: path.addPath(pointPath) pen = QPen(otherColor) pen.setWidthF(3.0 * scale) painter.save() painter.setPen(pen) painter.drawPath(path) painter.fillPath(path, QBrush(backgroundColor)) painter.drawPath(selectedPath) painter.fillPath(selectedPath, QBrush(otherColor)) painter.restore() # coordinates if drawCoordinates: otherColor = QColor(otherColor) otherColor.setAlphaF(otherColor.alphaF() * .6) painter.save() painter.setPen(otherColor) # TODO: decision + color font = painter.font() font.setPointSize(7) painter.setFont(font) for x, y in points: posX = x # TODO: We use + here because we align on top. Consider abstracting # yOffset. posY = y + 3 x = round(x, 1) if int(x) == x: x = int(x) y = round(y, 1) if int(y) == y: y = int(y) text = "%d %d" % (x, y) drawTextAtPoint(painter, text, posX, posY, scale, xAlign="center", yAlign="top") painter.restore()
from PyQt5.QtCore import QRectF, Qt from PyQt5.QtGui import QPainter, QPalette, QPainterPath from PyQt5.QtWidgets import ( QRubberBand, QStyle, QStyleOptionRubberBand, QApplication) from trufont.drawingTools.baseTool import BaseTool from trufont.tools import platformSpecific # Draw icon _path = QPainterPath() _path.setFillRule(Qt.WindingFill) _path.addRect(6, 14, 10, 10) _path.addEllipse(12, 6, 12, 12) class ShapesTool(BaseTool): icon = _path name = QApplication.translate("ShapesTool", "Shapes") shortcut = "S" def __init__(self, parent=None): super().__init__(parent) self._startPoint = None self._endPoint = None self._rubberBandRect = None def mousePressEvent(self, event): super().mousePressEvent(event) self._glyph.beginUndoGroup() self._startPoint = event.localPos() def mouseMoveEvent(self, event):