def __drawPoint(self, x, y, index): #横线 line1 = QGraphicsLineItem() line1.setPen(self.pen) line1.setLine(x - self.lineRadius, y, x + self.lineRadius, y) #竖线 line2 = QGraphicsLineItem() line2.setPen(self.pen) line2.setLine(x, y - self.lineRadius, x, y + self.lineRadius) #文字说明 text = QGraphicsTextItem() text.setDefaultTextColor(Qt.blue) text.setFont(self.font) text.setPlainText(self.pointsName[index]) text.setPos(x, y) #放到组中 pointGroup = QGraphicsItemGroup() pointGroup.addToGroup(line1) pointGroup.addToGroup(line2) pointGroup.addToGroup(text) #显示 if self.pointsItem[index] is not None: self.scene.removeItem(self.pointsItem[index]) #保存到字典 self.pointsItem[index] = pointGroup #显示该点 self.scene.addItem(self.pointsItem[index])
def refresh(self): if not self.items(): return super().refresh() for i in self.items(): if isinstance(i, QGraphicsLineItem): self.removeItem(i) hull = self.hull_method(self.point_model.points) pts = hull + [hull[0]] point_items = list(filter(lambda i: isinstance(i, PointGraphicsItem), self.items())) for p in point_items: p.setBrush(Qt.blue) min_point = min(point_items, key=lambda p:p.x()) min_point.setBrush(Qt.green) for i in range(len(pts)-1): dx, dy = pts[i+1].x - pts[i].x, pts[i+1].y - pts[i].y line = QGraphicsLineItem(pts[i+1].x, pts[i+1].y, pts[i+1].x+dx, pts[i+1].y+dy) pen = QPen() pen.setStyle(Qt.DashLine) line.setPen(pen) line.setZValue(-2) self.addItem(line) h_line = QGraphicsLineItem(pts[i].x, pts[i].y, pts[i+1].x, pts[i+1].y) h_line.setPen(Qt.red) h_line.setZValue(-1) self.enumeratePoints()
def add_clearance_graph(self): print("-----------------------------------------") horizontal_clearance = self.clearance_analysis.horizontal_clearance x_init = self.graph_zero[0] + self.line_extend y_init = self.graph_zero[1] for i in range(len(horizontal_clearance)): clearance_points = horizontal_clearance[i] x = x_init + i * self.dimension_analysis.section_distance * self.length_multiplier left = -self.dimension_analysis.domain_length right = self.dimension_analysis.domain_length if clearance_points[0]: left = clearance_points[0] if clearance_points[1]: right = clearance_points[1] clearance = right - left y_top = y_init + left * self.height_multiplier y_bottom = y_init + right * self.height_multiplier pen_red = QPen() red = Color.create_qcolor_from_rgb_tuple(Color.red) pen_red.setColor(red) pen_green = QPen() green = Color.create_qcolor_from_rgb_tuple(Color.green) pen_green.setColor(green) line = QGraphicsLineItem(x, y_top, x, y_bottom) if clearance < self.min_horizontal_clearance: line.setPen(pen_red) else: line.setPen(pen_green) self.addToGroup(line) pass
def draw_curve(self): curve = QLineF(self.origin_pos, self.current_pos) curve_item = QGraphicsLineItem(curve) curve_item.setPen(self.pen) curve_item.setFlag(QGraphicsItem.ItemIsMovable, True) self.addItem(curve_item) self.origin_pos = self.current_pos
def create_fromDB(self,pos_list=[],obj_type=""): if obj_type =="rois": num_rois = len(pos_list) for i in range(num_rois): points = pos_list[i] rect=QGraphicsRectItem() rect.setPen(QPen(Qt.green)) rect.setRect(points[0],points[1],points[2],points[3]) self.rectgroup.addToGroup(rect) self.scene.addItem(self.rectgroup) elif obj_type =="vector1": num_vec = len(pos_list) for i in range(num_vec): points = pos_list[i] vec=QGraphicsLineItem() vec.setPen(QPen(Qt.green)) vec.setLine(points[0],points[1],points[2],points[3]) self.linegroup.addToGroup(vec) self.scene.addItem(self.linegroup) elif obj_type =="vector2": num_vec = len(pos_list) for i in range(num_vec): points = pos_list[i] vec=QGraphicsLineItem() vec.setPen(QPen(Qt.green)) vec.setLine(points[0],points[1],points[2],points[3]) self.linegroup2.addToGroup(vec) self.scene.addItem(self.linegroup2)
def add_connecting_line(self, atom1, atom2): if atom1.y() > atom2.y(): y1 = atom1.y() + (atom1.boundingRect().height() * .5) y2 = atom2.y() + (atom2.boundingRect().height() * .5) elif atom1.y() < atom2.y(): y1 = atom1.y() + (atom1.boundingRect().height() * .5) y2 = atom2.y() + (atom2.boundingRect().height() * .5) else: y1 = atom1.y() + (atom1.boundingRect().height() * 0.5) y2 = atom2.y() + (atom2.boundingRect().height() * 0.5) if atom1.x() > atom2.x(): x1 = atom1.x() x2 = atom2.x() + atom2.boundingRect().width() elif atom1.x() < atom2.x(): x1 = atom1.x() + atom1.boundingRect().width() x2 = atom2.x() else: x1 = atom1.x() + (atom1.boundingRect().width() / 2) x2 = atom2.x() + (atom1.boundingRect().width() / 2) new_line = QGraphicsLineItem(x1, y1, x2, y2) pen = QtGui.QPen() pen.setColor(QtGui.QColor("#FAFAF7")) pen.setCosmetic(True) pen.setWidth(1) new_line.setPen(pen) self.scene.addItem(new_line)
def add_Line(self, l): assert isinstance(l, Line) line = QGraphicsLineItem(l.End_p[0].x, l.End_p[0].y, l.End_p[1].x, l.End_p[1].y) line.setPen(self.linePen) self.Line_list.append(line) self.gscene.addItem(line)
class RSegment(QObject): def __init__(self, x1, y1, x2, y2, color, line_width): self._x1 = x1 self._y1 = y1 self._x2 = x2 self._y2 = y2 self._pos = QPointF(x1, y1) super().__init__() self.line = QGraphicsLineItem() self.line.setLine(x1, y1, x2, y2) pen = QPen() pen.setWidthF(line_width) pen.setColor(color) self.line.setPen(pen) def x(self): return self._pos.x() def y(self): return self._pos.y() @pyqtProperty(QPointF) def pos(self): return self._pos @pos.setter def pos(self, value): delta_x = value.x() - self._pos.x() delta_y = value.y() - self._pos.y() self._x1 = self._x1 + delta_x self._y1 = self._y1 + delta_y self._x2 = self._x2 + delta_x self._y2 = self._y2 + delta_y self.line.setLine(self._x1, self._y1, self._x2, self._y2) self._pos = value
def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton: downPos = event.buttonDownPos(Qt.LeftButton) if not self.__tmpLine and self.__dragStartItem and \ (downPos - event.pos()).manhattanLength() > \ QApplication.instance().startDragDistance(): # Start a line drag line = QGraphicsLineItem(self) start = self.__dragStartItem.boundingRect().center() start = self.mapFromItem(self.__dragStartItem, start) line.setLine(start.x(), start.y(), event.pos().x(), event.pos().y()) pen = QPen(Qt.black, 4) pen.setCapStyle(Qt.RoundCap) line.setPen(pen) line.show() self.__tmpLine = line if self.__tmpLine: # Update the temp line line = self.__tmpLine.line() line.setP2(event.pos()) self.__tmpLine.setLine(line) QGraphicsWidget.mouseMoveEvent(self, event)
def mouseMoveEvent(self, event, image_item): if self._aiming: if self._helpLines is not None and self._helpLines.scene( ) is not None: self._scene.removeItem(self._helpLines) self._helpLines = QGraphicsItemGroup() group = self._helpLines verticalHelpLine = QGraphicsLineItem(event.scenePos().x(), 0, event.scenePos().x(), self._scene.height()) horizontalHelpLine = QGraphicsLineItem(0, event.scenePos().y(), self._scene.width(), event.scenePos().y()) horizontalHelpLine.setPen(self._helpLinesPen) verticalHelpLine.setPen(self._helpLinesPen) group.addToGroup(verticalHelpLine) group.addToGroup(horizontalHelpLine) self._scene.addItem(self._helpLines) else: if self._item is not None: assert self._init_pos is not None rect = QRectF(self._init_pos, event.scenePos()).normalized() self._item.setRect(rect) event.accept()
def importSVG(self, filepath, view): try: doc = minidom.parse(filepath) except (ExpatError, IsADirectoryError): # xml file is broken: we can't import it pass else: lines = doc.getElementsByTagName("line") for line in lines: x1 = line.getAttribute("x1") y1 = line.getAttribute("y1") x2 = line.getAttribute("x2") y2 = line.getAttribute("y2") width = line.getAttribute("width") lineItem = QGraphicsLineItem(float(x1), float(y1), float(x2), float(y2)) lineItem.setPen(QPen(view.colour, view.penRadius, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)) view.scene().addItem(lineItem) ellipses = doc.getElementsByTagName("ellipse") for ellipse in ellipses: cx = ellipse.getAttribute("cx") cy = ellipse.getAttribute("cy") rx = ellipse.getAttribute("rx") ry = ellipse.getAttribute("ry") width = ellipse.getAttribute("width") ellipseItem = QGraphicsEllipseItem(float(cx)-float(rx), float(cy)-float(ry), float(rx)*2, float(ry)*2) ellipseItem.setPen(QPen(view.colour, QtCore.Qt.SolidPattern)) ellipseItem.setBrush(view.colour) view.scene().addItem(ellipseItem)
class WayPoint: def __init__(self, **kwargs): super().__init__() self.location = MapPoint() self.__dict__.update(kwargs) self.pixmap = QGraphicsPixmapItem( QPixmap('HOME_DIR + /nparse/data/maps/waypoint.png')) self.pixmap.setOffset(-10, -20) self.line = QGraphicsLineItem(0.0, 0.0, self.location.x, self.location.y) self.line.setPen(QPen(Qt.green, 1, Qt.DashLine)) self.line.setVisible(False) self.pixmap.setZValue(5) self.line.setZValue(4) self.pixmap.setPos(self.location.x, self.location.y) def update_(self, scale, location=None): self.pixmap.setScale(scale) if location: line = self.line.line() line.setP1(QPointF(location.x, location.y)) self.line.setLine(line) pen = self.line.pen() pen.setWidth(1 / scale) self.line.setPen(pen) self.line.setVisible(True)
def moveTo(self, pos): #data coordinates oldX, oldY = self.pos.x(), self.pos.y() x, y = pos.x(), pos.y() line = QGraphicsLineItem(oldX, oldY, x, y) line.setPen( QPen(QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.scene.addItem(line) self._hasMoved = True #update bounding Box if not self.bb.isValid(): self.bb = QRect(QPoint(oldX, oldY), QSize(1, 1)) #grow bounding box self.bb.setLeft( min(self.bb.left(), max(0, x - self.brushSize // 2 - 1))) self.bb.setRight( max(self.bb.right(), min(self.sliceRect[0] - 1, x + self.brushSize // 2 + 1))) self.bb.setTop(min(self.bb.top(), max(0, y - self.brushSize // 2 - 1))) self.bb.setBottom( max(self.bb.bottom(), min(self.sliceRect[1] - 1, y + self.brushSize // 2 + 1))) #update/move position self.pos = pos
def drawObstacleWarnings(self, result): for item in self.obstacleMarkerShapes: self.augmentedRealityScene.removeItem(item) self.obstacleMarkerShapes.clear() shape0 = QGraphicsEllipseItem(-self.AugmentedRealityPanel.height() / 2, -self.AugmentedRealityPanel.height() / 2, self.AugmentedRealityPanel.height(), self.AugmentedRealityPanel.height()) shape0.setPen(QPen(self.black)) shape0.setOpacity(0.01) self.augmentedRealityScene.addItem(shape0) self.obstacleMarkerShapes.append(shape0) if (self.ObstacleWarningCB.isChecked()): markersToShow = np.zeros(self.numberOfObstacleGroupings) startAngle = result.angle_min angleIncrement = result.angle_increment AngleCutOff = 2 * np.pi / self.numberOfObstacleGroupings offset = np.pi/2 for point in range(0, len(result.ranges)): if result.ranges[point]<=self.obstacleWarningDistance: angle = startAngle + angleIncrement*point directionSector = int(angle/AngleCutOff) markersToShow[directionSector]=1 for marker in range(0, self.numberOfObstacleGroupings): if(markersToShow[marker]): shape = QGraphicsLineItem(-self.AugmentedRealityPanel.height()*0.98/2*math.cos(marker*AngleCutOff+offset),-self.AugmentedRealityPanel.height()*0.98/2*math.sin(marker*AngleCutOff+offset), -self.AugmentedRealityPanel.height()*0.98/2*math.cos((marker+1)*AngleCutOff+offset),-self.AugmentedRealityPanel.height()*0.98/2*math.sin((marker+1)*AngleCutOff+offset)) shape.setPen(QPen(self.red, 5)) self.augmentedRealityScene.addItem(shape) self.obstacleMarkerShapes.append(shape) self.AugmentedRealityPanel.centerOn(QPoint(0, 0))
def drawForever(self): line = QLineF(self.originPos, self.currentPos) line_item = QGraphicsLineItem(line) line_item.setPen(self.pen) line_item.setFlag(QGraphicsItem.ItemIsMovable, True) self.addItem(line_item) self.originPos = self.currentPos
def drawSegment(self): line = QLineF(self.originPos, self.currentPos) line_item = QGraphicsLineItem(line) line_item.setPen(self.pen) line_item.setFlag(QGraphicsItem.ItemIsMovable, True) if len(self.items()) > 0: self.clearLastItem() self.addItem(line_item)
def draw_line(self): line = QLineF(self.origin_pos, self.current_pos) line_item = QGraphicsLineItem(line) line_item.setPen(self.pen) line_item.setFlag(QGraphicsItem.ItemIsMovable, True) if len(self.items()) > 0: self.clear_last_item() self.addItem(line_item)
def distance_to(self, item): distance = QLineF(QPointF(self.pos().x() + 25, self.pos().y() + 25), item.pos()) line = QGraphicsLineItem(distance) line.setPen(QPen(Qt.red)) # self.scene().addItem(line) return distance.length()
def draw_line(self): line_pen = QPen(Qt.black, 2) item = QGraphicsLineItem(0, self.h, self.w, self.h) item.setPen(line_pen) self.scene.addItem(item) item = QGraphicsLineItem(self.w, 0, self.w, self.h) item.setPen(line_pen) self.scene.addItem(item)
def add_graphics_line_item(self, line): line_item = QGraphicsLineItem(line) line_item.setPen(self.pen) line_item.setZValue(-1) scene = self.model.gui.scene scene.addItem(line_item) pair = (line, line_item) self.line_pairs.append(pair) return pair
def drawLinesFromOriginToPoints(self): points = self.algorithm.stageResults[1] for p in points: line = QGraphicsLineItem(self.originItem.x(), self.originItem.y(), p.x, p.y) pen = QPen() pen.setStyle(Qt.DashLine) line.setPen(pen) line.setZValue(-1) self.addItem(line)
def drawLrLine(self): leftmost = list(filter(lambda i: i.point == self.algorithm.stageResults[0][0], self.items()))[0] rightmost = list(filter(lambda i: i.point == self.algorithm.stageResults[0][1], self.items()))[0] leftmost.setBrush(Qt.red) rightmost.setBrush(Qt.red) lr_line = QGraphicsLineItem(leftmost.x(), leftmost.y(), rightmost.x(), rightmost.y()) lr_line.setPen(Qt.red) lr_line.setZValue(-1) self.addItem(lr_line)
def updateCurve(self, name, color=Qt.black): # if name in self.curveObjs: # curveitem = self.curveObjs[name] # else: # curveitem = QGraphicsPathItem() # self.scene.addItem(curveitem) # # path=curveitem.path() # path = QPainterPath() # # pointItems = self.curvePointObjs[name] # if len(pointItems) > 0: # path.moveTo(pointItems[0].pos()) # for pointitem in pointItems[1:]: # path.lineTo(pointitem.pos()) # curveitem.setPath(path) # curveitem.update(curveitem.boundingRect()) # curveitem.prepareGeometryChange() # self.scene.update() # self.viewport().repaint() # self.viewport().update() if not isinstance(name, str): return if name not in self.pointObjs: return lastitems = [] if name in self.curveObjs: lastitems = self.curveObjs[name] if not isinstance(lastitems, list): lastitems = [] if name in self.pointObjs: pointItems = self.pointObjs[name] else: pointItems = [] points = [] for ptitem in pointItems: points.append(ptitem.pos()) self.curveObjs[name] = [] if len(points) > 1: for i in range(1, len(points)): l = QGraphicsLineItem(points[i - 1].x(), points[i - 1].y(), points[i].x(), points[i].y()) l.setPen(color) l.setZValue(10) # l.setFlag(QGraphicsItem.ItemIsSelectable) self.curveObjs[name].append(l) self.scene.addItem(l) for line in lastitems: self.scene.removeItem(line) self.updateCurvePoints(name)
def updateGraphicsLineItem(line: QGraphicsLineItem, lineF: QLineF = None, pen: QPen = None): """ 更新线 QGraphicsLineItem属性 :param line: QGraphicsLineItem :param lineF: 线的坐标大小 :param pen: 画笔 """ if lineF: line.setLine(lineF) if pen: line.setPen(pen)
def add_dummy_line_for_margin(self): height = self.scene.height() width = self.scene.width() pen = QPen() pen.setStyle(Qt.NoPen) dummy_line_a= QGraphicsLineItem(0, height, 0, height + 100) dummy_line_b = QGraphicsLineItem(width, 0, width + 100, 0) dummy_line_a.setPen(pen) dummy_line_b.setPen(pen) self.scene.addItem(dummy_line_a) self.scene.addItem(dummy_line_b)
def fire(self): arrow = Arrow() arrow.setPos(self.x(), self.y()) attack_line = QLineF(QPointF(self.x() + 25, self.y() + 25), self.attack_destination) line = QGraphicsLineItem(attack_line) line.setPen(QPen(Qt.blue)) # self.scene().addItem(line) attack_angle = -1 * attack_line.angle( ) # Multiplied by -1 because the angle is given in counter clockwise direction arrow.setRotation(attack_angle) self.scene().addItem(arrow)
class CrosshairGraphicsItem(QObject): def __init__(self, parent=None): super().__init__(parent) self.horizontal_line = QGraphicsLineItem() self.vertical_line = QGraphicsLineItem() self.horizontal_line.setLine(0, 1080 / 2, 1920, 1080 / 2) self.vertical_line.setLine(1920 / 2, 0, 1920 / 2, 1080) self.pen = QPen(Qt.white) self.horizontal_line.setPen(self.pen) self.vertical_line.setPen(self.pen)
def __init__(self, parent, color): super().__init__(None) self.color = QColor(color) self.pen = QPen() self.pen.setColor(self.color) self.lines = [] self.offset_x = 10 for x in range(self.offset_x, 500 + self.offset_x): line = QGraphicsLineItem(self) line.setLine(x, 20 + 200, x + 1, 20 + 200) line.setPen(self.pen) self.lines.append(line)
def create_axis(self): bounding_end = abs(self.dimension_analysis.bounding_rect[3]) bounding_start = abs(self.dimension_analysis.bounding_rect[2]) pen = QPen() pen.setWidthF(0.5) # horizontal line self.graph_zero[0] = self.position[0] + self.margin - self.line_extend self.graph_zero[1] = self.position[1] + bounding_start * self.height_multiplier + self.margin self.graph_end[0] = self.graph_zero[0] + self.content_width + self.line_extend self.graph_end[1] = self.graph_zero[1] line_item_horizontal = QGraphicsLineItem(self.graph_zero[0], self.graph_zero[1], self.graph_end[0], self.graph_end[1]) line_item_horizontal.setPen(pen) self.addToGroup(line_item_horizontal) center = (self.graph_zero[0] + self.line_extend), self.graph_zero[1] y_top = center[1] - (bounding_start*self.height_multiplier) y_bottom = center[1]+(bounding_end*self.height_multiplier) line_item_vertical = QGraphicsLineItem(center[0], y_top, center[0], y_bottom) line_item_vertical.setPen(pen) self.addToGroup(line_item_vertical) pen_thin = QPen() pen_thin.setWidthF(0.2) start_graph = center[1] - 10 while start_graph > center[1] - bounding_start * self.height_multiplier: line_item_horizontal = QGraphicsLineItem(self.graph_zero[0], start_graph, self.graph_end[0], start_graph) line_item_horizontal.setPen(pen_thin) line_item_horizontal.setZValue(-0.5) self.addToGroup(line_item_horizontal) start_graph -= 10 start_graph = center[1] + 10 while start_graph < center[1] + bounding_end * self.height_multiplier: line_item_horizontal = QGraphicsLineItem(self.graph_zero[0], start_graph, self.graph_end[0], start_graph) line_item_horizontal.setPen(pen_thin) line_item_horizontal.setZValue(-0.5) self.addToGroup(line_item_horizontal) start_graph += 10
def drawHlrLines(self): hlr = self.algorithm.stageResults[1] for h, l, r in hlr: pen = QPen() pen.setStyle(Qt.PenStyle.DashLine) lh_line = QGraphicsLineItem(l.x, l.y, h.x, h.y) lh_line.setPen(pen) lh_line.setZValue(-1) rh_line = QGraphicsLineItem(r.x, r.y, h.x, h.y) rh_line.setPen(pen) rh_line.setZValue(-1) self.addItem(lh_line) self.addItem(rh_line)
def __init__(self, *args, **kwargs): self.width = kwargs.pop('width', 1) self.height = kwargs.pop('height', 1) self.pickup_point = kwargs.pop('pickup_point', False) self.draw_corners = kwargs.pop('draw_corners', False) self.scale = kwargs.pop('scale', 1) super().__init__(*args, **kwargs) self._lines = [] self._linesF = [] self._points = [] self._pointsF = [] self.pickupPointX = 50 self.pickupPointY = 50 self._circleDia = 2.0 self._linePen = QPen(QColor(135, 208, 80)) self._linePen.setCapStyle(Qt.RoundCap) self._circlePen = QPen(QColor(66, 66, 66)) self._pickupPen = QPen(QColor(135, 66, 66)) self._linePen.setCapStyle(Qt.RoundCap) self._circlePen.setCapStyle(Qt.RoundCap) self._pickupPen.setCapStyle(Qt.RoundCap) self._linePen.setWidth(1) self._circlePen.setWidth(2) self._pickupPen.setWidth(2) for i in range(4): l = QGraphicsLineItem() l.setPen(self._linePen) self._lines.append(l) self._linesF.append(QLineF()) for i in range(4): self._pointsF.append(QPointF(0.0, 0.0)) if self.draw_corners: for i in range(4): e = QGraphicsCircleItem(diameter=self._circleDia) e.setPen(self._circlePen) self._points.append(e) if self.pickup_point: self._pickupPointF = QPointF() self._pickupPoint = QGraphicsCircleItem(diameter=self._circleDia) self._pickupPoint.setPen(self._pickupPen)
def generateData(self, canvas, lines, params): scene = QGraphicsScene() scene.setSceneRect(canvas) group = scene.createItemGroup([]) for line in lines: clone = QGraphicsLineItem(line) clone.setLine(line.line()) clone.setPen(line.pen()) scene.addItem(clone) group.addToGroup(clone) pixmaps = [] for i in xrange(params.count): pixmaps.append(self.generateRandom(scene, group, canvas, params)) return pixmaps
class RSegment(QObject): def __init__(self, x1, y1, l, a, color, line_width): self._point_radius = 3 self._angle = a self._length = l self._x1 = x1 self._y1 = y1 self._x2 = x1 + self._length * math.cos(self._angle) self._y2 = y1 + self._length * math.sin(self._angle) self._pos = QVector3D(x1, y1, self._angle) super().__init__() self.line = QGraphicsLineItem() self.rect = QRectF(x1 - self._point_radius, y1 - self._point_radius, 2 * self._point_radius, 2 * self._point_radius) self.point = QGraphicsEllipseItem() self.point.setRect(self.rect) self.line.setLine(self._x1, self._y1, self._x2, self._y2) pen = QPen() pen.setWidthF(line_width) pen.setColor(color) self.line.setPen(pen) self.point.setPen(pen) def x(self): return self._x1 def y(self): return self._y1 def angle(self): return self._angle @pyqtProperty(QVector3D) def pos(self): return self._pos @pos.setter def pos(self, value): self._pos = value self._x1 = self._pos.x() self._y1 = self._pos.y() self._angle = value.z() self._x2 = self._x1 + self._length * math.cos(self._angle) self._y2 = self._y1 + self._length * math.sin(self._angle) self.line.setLine(self._x1, self._y1, self._x2, self._y2) self.rect = QRectF(self._x1 - self._point_radius, self._y1 - self._point_radius, 2 * self._point_radius, 2 * self._point_radius) self.point.setRect(self.rect)
def make_cursor(self): pen = QPen(QColor(0, 255, 0)) h_line = QGraphicsLineItem(-10, 0, 10, 0) v_line = QGraphicsLineItem(0, -10, 0, 10) pen.setWidth(1) h_line.setPen(pen) v_line.setPen(pen) self.point_cursor = QGraphicsItemGroup() self.point_cursor.addToGroup(h_line) self.point_cursor.addToGroup(v_line) self.point_cursor.setZValue(1) self.point_cursor.setVisible(False) self.scene().addItem(self.point_cursor)
def __init__(self, origX, origY, perCell, n): super(GridItem, self).__init__(); length = perCell*n/2; pen = QPen(Qt.DashLine); pen.setColor(QColor(230, 230, 230)) pen.setWidth(0); x1, y1, x2, y2 = origX-length, origY-length, origX-length, origY+length for i in range(1, n): line = QGraphicsLineItem(x1, y1, x2, y2, self) line.setPen(pen) x1, y1, x2, y2 = x1+perCell, y1, x2+perCell, y2 x1, y1, x2, y2 = origX-length, origY-length, origX+length, origY-length for i in range(1, n): line = QGraphicsLineItem(x1, y1, x2, y2, self) line.setPen(pen) x1, y1, x2, y2 = x1, y1+perCell, x2, y2+perCell
def createArrow(self): rad = self._RADIUS pen = QPen() pen.setWidth(3) color = QColor(Qt.blue) color.setAlphaF(0.25) pen.setBrush(color) if self._virtual_helix.isEvenParity(): arrow = QGraphicsLineItem(rad, rad, 2*rad, rad, self) else: arrow = QGraphicsLineItem(0, rad, rad, rad, self) arrow.setTransformOriginPoint(rad, rad) arrow.setZValue(400) arrow.setPen(pen) self.arrow = arrow self.arrow.hide()
def drawNewFence(self, fps): self.clearFencePoints() prev_fp = None for i in range(1, len(fps)): if prev_fp is not None: prev_x = prev_fp.lon prev_y = -prev_fp.lat mapped_x = fps[i].lon mapped_y = -fps[i].lat next_line = QGraphicsLineItem(prev_x, prev_y, mapped_x, mapped_y, self.__fence_layer) l_pen = QPen(QColor(0, 255, 0)) l_pen.setWidth(0.1) next_line.setPen(l_pen) self.__fence_layer.addToGroup(next_line) prev_fp = fps[i]
def moveTo(self, pos): # data coordinates oldX, oldY = self.pos.x(), self.pos.y() x, y = pos.x(), pos.y() line = QGraphicsLineItem(oldX, oldY, x, y) line.setPen(QPen(QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.scene.addItem(line) self._hasMoved = True # update bounding Box if not self.bb.isValid(): self.bb = QRect(QPoint(oldX, oldY), QSize(1, 1)) # grow bounding box self.bb.setLeft(min(self.bb.left(), max(0, x - self.brushSize // 2 - 1))) self.bb.setRight(max(self.bb.right(), min(self.sliceRect[0] - 1, x + self.brushSize // 2 + 1))) self.bb.setTop(min(self.bb.top(), max(0, y - self.brushSize // 2 - 1))) self.bb.setBottom(max(self.bb.bottom(), min(self.sliceRect[1] - 1, y + self.brushSize // 2 + 1))) # update/move position self.pos = pos
def drawGrid(self): black_notes = [2,4,6,9,11] scale_bar = QGraphicsRectItem(0, 0, self.grid_width, self.note_height, self.piano) scale_bar.setPos(self.piano_width, 0) scale_bar.setBrush(QColor(100,100,100)) clearpen = QPen(QColor(0,0,0,0)) for i in range(self.end_octave - self.start_octave, self.start_octave - self.start_octave, -1): for j in range(self.notes_in_octave, 0, -1): scale_bar = QGraphicsRectItem(0, 0, self.grid_width, self.note_height, self.piano) scale_bar.setPos(self.piano_width, self.note_height * j + self.octave_height * (i - 1)) scale_bar.setPen(clearpen) if j not in black_notes: scale_bar.setBrush(QColor(120,120,120)) else: scale_bar.setBrush(QColor(100,100,100)) measure_pen = QPen(QColor(0, 0, 0, 120), 3) half_measure_pen = QPen(QColor(0, 0, 0, 40), 2) line_pen = QPen(QColor(0, 0, 0, 40)) for i in range(0, int(self.num_measures) + 1): measure = QGraphicsLineItem(0, 0, 0, self.piano_height + self.header_height - measure_pen.width(), self.header) measure.setPos(self.measure_width * i, 0.5 * measure_pen.width()) measure.setPen(measure_pen) if i < self.num_measures: number = QGraphicsSimpleTextItem('%d' % (i + 1), self.header) number.setPos(self.measure_width * i + 5, 2) number.setBrush(Qt.white) for j in self.frange(0, self.time_sig[0]*self.grid_div/self.time_sig[1], 1.): line = QGraphicsLineItem(0, 0, 0, self.piano_height, self.header) line.setZValue(1.0) line.setPos(self.measure_width * i + self.value_width * j, self.header_height) if j == self.time_sig[0]*self.grid_div/self.time_sig[1] / 2.0: line.setPen(half_measure_pen) else: line.setPen(line_pen)
def onMouseMove_draw(self, imageview, event): self._navIntr.onMouseMove_default(imageview, event) o = imageview.scene().data2scene.map(QPointF(imageview.oldX, imageview.oldY)) n = imageview.scene().data2scene.map(QPointF(imageview.x, imageview.y)) # Draw temporary line for the brush stroke so the user gets feedback before the data is really updated. pen = QPen( QBrush(self._brushingCtrl._brushingModel.drawColor), self._brushingCtrl._brushingModel.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin, ) line = QGraphicsLineItem(o.x(), o.y(), n.x(), n.y()) line.setPen(pen) imageview.scene().addItem(line) line.setParentItem(imageview.scene().dataRectItem) self._lineItems.append(line) self._brushingCtrl._brushingModel.moveTo(imageview.mousePos)
def drawWPLine(self, wp1, wp2): if wp1 is None or wp2 is None: print("Error: Can't draw line for Null endpoint") return rad = self.__wp_diameter * 0.5 mapped_wp1_x = wp1.y - rad mapped_wp1_y = -wp1.x #tangential approach? if (wp1.command == mavutil.mavlink.MAV_CMD_NAV_LOITER_TO_ALT and wp1.param1 == 1.0): l_rad = abs(self.__wp_loiter_radius) if l_rad is not None: dis = acs_math.gps_distance(wp1.x, wp1.y, wp2.x, wp2.y) theta = math.degrees(math.atan(l_rad / dis)) #sign of self.__wp_loiter_radius indicates the direction of the #loiter (negative is counter-clockwise, postive is clockwise) #Also, the waypoint itself can override the default setting #via param2 if ((wp1.param2 == 0 and self.__wp_loiter_radius > 0.0) or wp1.param2 > 0.0): theta = -theta tan_dis = math.sqrt( dis * dis - l_rad * l_rad) bearing = acs_math.gps_bearing(wp2.x, wp2.y, wp1.x, wp1.y) (tan_wp_x, tan_wp_y) = acs_math.gps_newpos(wp2.x, wp2.y, bearing - theta, tan_dis) mapped_wp1_x = tan_wp_y - rad mapped_wp1_y = -tan_wp_x next_line = QGraphicsLineItem(mapped_wp1_x, mapped_wp1_y, wp2.y - rad, -wp2.x, self.__mission_layer) l_pen = QPen(QColor(255, 255, 255)) l_pen.setWidth(0.00002) next_line.setPen(l_pen) self.__mission_layer.addToGroup(next_line)
def create_axis(self): counter = 0 while self.surface[0][counter] is None: #get the first tile counter += 1 # determining the distance from left side left_coordinate = abs(self.surface[0][counter].point.X()) distance = (left_coordinate + counter * self.sampling_distance) * self.height_multiplier pen = QPen() pen.setWidthF(0.5) self.graph_zero[0] = self.position[0] + self.margin - self.line_extend self.graph_zero[1] = self.position[1] + distance + self.margin self.graph_end[0] = self.graph_zero[0] + self.content_width + self.line_extend self.graph_end[1] = self.graph_zero[1] line_item_horizontal = QGraphicsLineItem(self.graph_zero[0], self.graph_zero[1], self.graph_end[0], self.graph_end[1]) line_item_horizontal.setPen(pen) self.addToGroup(line_item_horizontal) center = (self.graph_zero[0] + self.line_extend), self.graph_zero[1] y_top = center[1] - distance y_bottom = self.position[1] + self.margin + len(self.surface[0]) * self.sampling_distance * self.height_multiplier line_item_vertical = QGraphicsLineItem(center[0], y_top, center[0], y_bottom) line_item_vertical.setPen(pen) self.addToGroup(line_item_vertical)
def createArrows(self): rad = _RADIUS pen1 = self._pen1 pen2 = self._pen2 pen1.setWidth(3) pen2.setWidth(3) pen1.setBrush(Qt.gray) pen2.setBrush(Qt.lightGray) if self._virtual_helix.isEvenParity(): arrow1 = QGraphicsLineItem(rad, rad, 2*rad, rad, self) arrow2 = QGraphicsLineItem(0, rad, rad, rad, self) else: arrow1 = QGraphicsLineItem(0, rad, rad, rad, self) arrow2 = QGraphicsLineItem(rad, rad, 2*rad, rad, self) arrow1.setTransformOriginPoint(rad, rad) arrow2.setTransformOriginPoint(rad, rad) arrow1.setZValue(400) arrow2.setZValue(400) arrow1.setPen(pen1) arrow2.setPen(pen2) self.arrow1 = arrow1 self.arrow2 = arrow2 self.arrow1.hide() self.arrow2.hide()
class ParticipantItem(QGraphicsItem): def __init__(self, model_item: Participant, parent=None): super().__init__(parent) self.model_item = model_item self.text = QGraphicsTextItem(self) self.line = QGraphicsLineItem(self) self.line.setPen(QPen(Qt.darkGray, 1, Qt.DashLine, Qt.RoundCap, Qt.RoundJoin)) self.refresh() def update_position(self, x_pos=-1, y_pos=-1): if x_pos == -1: x_pos = self.x_pos() if y_pos == -1: y_pos = self.line.line().y2() self.text.setPos(x_pos - (self.text.boundingRect().width() / 2), 0) self.line.setLine(x_pos, 30, x_pos, y_pos) def x_pos(self): return self.line.line().x1() def width(self): return self.boundingRect().width() def refresh(self): self.text.setPlainText("?" if not self.model_item else self.model_item.shortname) if hasattr(self.model_item, "simulate") and self.model_item.simulate: font = QFont() font.setBold(True) self.text.setFont(font) self.text.setDefaultTextColor(Qt.darkGreen) self.line.setPen(QPen(Qt.darkGreen, 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) else: self.text.setFont(QFont()) self.text.setDefaultTextColor(constants.LINECOLOR) self.line.setPen(QPen(Qt.darkGray, 1, Qt.DashLine, Qt.RoundCap, Qt.RoundJoin)) def boundingRect(self): return self.childrenBoundingRect() def paint(self, painter, option, widget): pass
class AnalogClock(Desklet): def __init__(self): super().__init__() self.center_x = 0 self.center_y = 0 self.radius = 1 self.now = datetime.utcfromtimestamp(0) # build the clock face self.circle = QGraphicsEllipseItem(self.root) self.lines = [] for _ in range(0, 60): self.lines.append(QGraphicsLineItem(self.root)) self.hours_hand = QGraphicsLineItem(self.root) self.minutes_hand = QGraphicsLineItem(self.root) self.seconds_hand = QGraphicsLineItem(self.root) self.hand_circle = QGraphicsEllipseItem(self.root) def set_style(self, style): super().set_style(style) # minute pen = QPen(self.style.foreground_color) pen.setWidth(12) pen.setCapStyle(Qt.RoundCap) self.minutes_hand.setPen(pen) # hour pen = QPen(self.style.foreground_color) pen.setWidth(16) pen.setCapStyle(Qt.RoundCap) self.hours_hand.setPen(pen) # second pen = QPen(self.style.midcolor) pen.setWidth(4) pen.setCapStyle(Qt.RoundCap) self.seconds_hand.setPen(pen) # outer circle pen = QPen(self.style.foreground_color) pen.setWidth(6) self.circle.setPen(pen) # inner circle self.hand_circle.setBrush(QBrush(self.style.background_color)) # minute lines pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(self.style.midcolor) pen.setWidth(4) bold_pen = QPen() bold_pen.setCapStyle(Qt.RoundCap) bold_pen.setColor(self.style.foreground_color) bold_pen.setWidth(6) for i, line in enumerate(self.lines): if i % 5 == 0: line.setPen(bold_pen) else: line.setPen(pen) self.layout() def set_rect(self, rect): super().set_rect(rect) self.layout() def layout(self): self.center_x = self.rect.left() + self.rect.width() / 2.0 self.center_y = self.rect.top() + self.rect.height() / 2.0 self.radius = min(self.rect.width(), self.rect.height()) / 2.0 - 3.0 self.circle.setRect(self.center_x - self.radius, self.center_y - self.radius, 2 * self.radius, 2 * self.radius) self.hand_circle.setRect(self.center_x - 5, self.center_y - 5, 10, 10) for i, line in enumerate(self.lines): angle = i * 2.0 * math.pi / 60.0 if i % 5 == 0: line.setLine(self.center_x + math.cos(angle) * self.radius * 0.85, self.center_y + math.sin(angle) * self.radius * 0.85, self.center_x + math.cos(angle) * self.radius * 0.95, self.center_y + math.sin(angle) * self.radius * 0.95) else: line.setLine(self.center_x + math.cos(angle) * self.radius * 0.90, self.center_y + math.sin(angle) * self.radius * 0.90, self.center_x + math.cos(angle) * self.radius * 0.95, self.center_y + math.sin(angle) * self.radius * 0.95) self.update(self.now) def update(self, now): self.now = now hour = (self.now.hour / 12.0 + self.now.minute / 60.0 / 12.0) * 2.0 * math.pi - math.pi / 2.0 minute = (self.now.minute / 60.0 + self.now.second / 60.0 / 60.0) * 2.0 * math.pi - math.pi / 2.0 second = (self.now.second / 60.0) * 2.0 * math.pi - math.pi / 2.0 self.set_seconds(second) self.set_minutes(minute) self.set_hours(hour) def set_seconds(self, n): self.seconds_hand.setLine( self.center_x + math.cos(n) * self.radius * 0.0, self.center_y + math.sin(n) * self.radius * 0.0, self.center_x + math.cos(n) * self.radius * 0.8, self.center_y + math.sin(n) * self.radius * 0.8) def set_minutes(self, n): self.minutes_hand.setLine( self.center_x + math.cos(n) * self.radius * 0.0, self.center_y + math.sin(n) * self.radius * 0.0, self.center_x + math.cos(n) * self.radius * 0.8, self.center_y + math.sin(n) * self.radius * 0.8) def set_hours(self, n): self.hours_hand.setLine( self.center_x + math.cos(n) * self.radius * 0.0, self.center_y + math.sin(n) * self.radius * 0.0, self.center_x + math.cos(n) * self.radius * 0.45, self.center_y + math.sin(n) * self.radius * 0.45)
class BaseGraphic(object): def __init__(self, *args): super(BaseGraphic, self).__init__() self.label = args[3] self.parent = args[0] self.section_analyzer = self.parent.section_analyzer self.width = None self.height = None self.margin = None self.position = args[1], args[2] self.content_width = None self.content_height = None self.distance_pointer = None self.distance_label = None self.section_num = len(self.section_analyzer.section_list) self.section_distance = self.section_analyzer.section_distance self.length_multiplier = 100.0 self.height_multiplier = 100.0 self.line_extend = 20 self.margin = 50 self.material_legend = MaterialLegend(self) self._inited = False self.items = [] self.add_title() def add_title(self): if self.label: title = QGraphicsSimpleTextItem(self.label) title.setPos(self.position[0] + self.margin, self.position[1] + self.line_extend) self.addToGroup(title) def addToGroup(self, item): self.items.append(item) def create_distance_pointer(self): self.distance_pointer = QGraphicsLineItem() pen = QPen() pen.setWidthF(1.0) pen.setStyle(Qt.DashDotLine) color = Color.create_qcolor_from_rgb_tuple_f((1,0,0)) pen.setColor(color) self.distance_pointer.setPen(pen) self.distance_pointer.setZValue(1.0) self.addToGroup(self.distance_pointer) self.distance_label = QGraphicsSimpleTextItem() self.distance_label.setZValue(1.0) self.addToGroup(self.distance_label) def init_dimension(self): section_num = len(self.section_analyzer.section_list) section_distance = self.section_analyzer.section_distance self.content_width = section_num * section_distance * self.length_multiplier self.create_distance_pointer() self._inited = True def update_graph_size(self): if self.content_height and self.content_width: self.width = self.content_width + self.margin * 2 self.height = self.content_height + self.margin * 2 # bounding_rect.setWidth(self.width) # bounding_rect.setHeight(self.height) def set_distance_pointer(self, distance): if self._inited: x1 = self.position[0] + self.margin + distance * self.length_multiplier y1 = self.position[1] x2 = x1 y2 = y1 + self.height self.distance_pointer.setLine(x1, y1, x2, y2) self.distance_label.setText("%.2f" % distance) self.distance_label.setPos(x2,y2) pass @staticmethod def set_rect_fill(*args): if args[0] == 0: #surface color mode rect = args[1] color = args[2] qcolor = Color.create_qcolor_from_rgb_tuple_f(color) brush = QBrush(qcolor) rect.setBrush(brush) def create_legend(self): x = self.position[0] + self.width y = self.position[1] self.material_legend.create_material_legend(x, y) for item in self.material_legend.graphic_items: self.addToGroup(item)
def add_dummy_line(self): pen = QPen() pen.setStyle(Qt.NoPen) dummy_line = QGraphicsLineItem(0, 0, 0, 100) dummy_line.setPen(pen) self.scene.addItem(dummy_line)
class CalendarDesklet(Desklet): def __init__(self): super().__init__() self.model = CalendarModel() self.cursor_pos = None self.cursor = QGraphicsRectItem(self.root) self.header = QGraphicsSimpleTextItem(self.root) self.weekdays = [] days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] for day in days: self.weekdays.append(QGraphicsSimpleTextItem(day, self.root)) self.header_line = QGraphicsLineItem(self.root) self.days = [] for _ in range(0, 6 * 7): self.days.append(QGraphicsSimpleTextItem(self.root)) def next_month(self): self.model.next_month() self.layout() def previous_month(self): self.model.previous_month() self.layout() def set_rect(self, rect): super().set_rect(rect) self.layout() def set_style(self, style): super().set_style(style) font = QFont(style.font) font.setPixelSize(48) self.header.setBrush(style.midcolor) self.header.setFont(font) font = QFont(style.font) font.setPixelSize(32) self.header_line.setPen(style.foreground_color) self.cursor.setBrush(style.midcolor) self.cursor.setPen(QPen(Qt.NoPen)) for widget in self.weekdays: widget.setFont(font) widget.setBrush(style.foreground_color) for widget in self.days: widget.setFont(font) widget.setBrush(self.style.foreground_color) self.layout() def layout(self): cell_width = (self.rect.width()) / 7.0 cell_height = (self.rect.height() - 64) / 7.0 x = self.rect.left() y = self.rect.top() fm = QFontMetrics(self.header.font()) rect = fm.boundingRect(self.header.text()) self.header.setPos(x + self.rect.width() / 2 - rect.width() / 2, y) y += fm.height() for row, day in enumerate(self.weekdays): fm = QFontMetrics(day.font()) rect = fm.boundingRect(day.text()) day.setPos(x + row * cell_width + cell_width / 2 - rect.width() / 2, y) y += fm.height() self.header_line.setLine(x, y, x + self.rect.width() - 3, y) y += 8 for n, widget in enumerate(self.days): col = n % 7 row = n // 7 rect = fm.boundingRect(widget.text()) widget.setPos(x + col * cell_width + cell_width / 2 - rect.width() / 2, y + row * cell_height + cell_height / 2 - fm.height() / 2) # if day.month != self.now.month: # widget.setBrush(self.style.midcolor) # else: if self.cursor_pos is not None: self.cursor.setRect(x + self.cursor_pos[0] * cell_width, y + self.cursor_pos[1] * cell_height, cell_width, cell_height) self.cursor.show() else: self.cursor.hide() def update(self, now): self.model.update(now) # update header self.header.setText( date(self.model.year, self.model.month, 1).strftime("%B %Y")) # calculate the date of the top/left calendar entry current_date = date(self.model.year, self.model.month, 1) current_date = current_date - timedelta(current_date.weekday()) self.cursor_pos = None for n, widget in enumerate(self.days): col = n % 7 row = n // 7 if current_date == self.model.today: self.cursor_pos = (col, row) widget.setText("%d" % current_date.day) self.days[n] = widget current_date += timedelta(days=1) self.layout()
class PianoRoll(QGraphicsScene): '''the piano roll''' midievent = pyqtSignal(list) measureupdate = pyqtSignal(int) modeupdate = pyqtSignal(str) def __init__(self, time_sig = '4/4', num_measures = 4, quantize_val = '1/8'): QGraphicsScene.__init__(self) self.setBackgroundBrush(QColor(50, 50, 50)) self.mousePos = QPointF() self.notes = [] self.selected_notes = [] self.piano_keys = [] self.marquee_select = False self.insert_mode = False self.velocity_mode = False self.place_ghost = False self.ghost_note = None self.default_ghost_vel = 100 self.ghost_vel = self.default_ghost_vel ## dimensions self.padding = 2 ## piano dimensions self.note_height = 10 self.start_octave = -2 self.end_octave = 8 self.notes_in_octave = 12 self.total_notes = (self.end_octave - self.start_octave) \ * self.notes_in_octave + 1 self.piano_height = self.note_height * self.total_notes self.octave_height = self.notes_in_octave * self.note_height self.piano_width = 34 ## height self.header_height = 20 self.total_height = self.piano_height - self.note_height + self.header_height #not sure why note_height is subtracted ## width self.full_note_width = 250 # i.e. a 4/4 note self.snap_value = None self.quantize_val = quantize_val ### dummy vars that will be changed self.time_sig = 0 self.measure_width = 0 self.num_measures = 0 self.max_note_length = 0 self.grid_width = 0 self.value_width = 0 self.grid_div = 0 self.piano = None self.header = None self.play_head = None self.setTimeSig(time_sig) self.setMeasures(num_measures) self.setGridDiv() self.default_length = 1. / self.grid_div # ------------------------------------------------------------------------- # Callbacks def movePlayHead(self, transport_info): # TODO: need conversion between frames and PPQ x = 105. # works for 120bpm total_duration = self.time_sig[0] * self.num_measures * x pos = transport_info['frame'] / x frac = (pos % total_duration) / total_duration self.play_head.setPos(QPointF(frac * self.grid_width, 0)) def setTimeSig(self, time_sig): try: new_time_sig = list(map(float, time_sig.split('/'))) if len(new_time_sig)==2: self.time_sig = new_time_sig self.measure_width = self.full_note_width * self.time_sig[0]/self.time_sig[1] self.max_note_length = self.num_measures * self.time_sig[0]/self.time_sig[1] self.grid_width = self.measure_width * self.num_measures self.setGridDiv() except ValueError: pass def setMeasures(self, measures): try: self.num_measures = float(measures) self.max_note_length = self.num_measures * self.time_sig[0]/self.time_sig[1] self.grid_width = self.measure_width * self.num_measures self.refreshScene() except: pass def setDefaultLength(self, length): try: v = list(map(float, length.split('/'))) if len(v) < 3: self.default_length = \ v[0] if len(v)==1 else \ v[0] / v[1] pos = self.enforce_bounds(self.mousePos) if self.insert_mode: self.makeGhostNote(pos.x(), pos.y()) except ValueError: pass def setGridDiv(self, div=None): if not div: div = self.quantize_val try: val = list(map(int, div.split('/'))) if len(val) < 3: self.quantize_val = div self.grid_div = val[0] if len(val)==1 else val[1] self.value_width = self.full_note_width / float(self.grid_div) if self.grid_div else None self.setQuantize(div) self.refreshScene() except ValueError: pass def setQuantize(self, value): try: val = list(map(float, value.split('/'))) if len(val) == 1: self.quantize(val[0]) self.quantize_val = value elif len(val) == 2: self.quantize(val[0] / val[1]) self.quantize_val = value except ValueError: pass # ------------------------------------------------------------------------- # Event Callbacks def keyPressEvent(self, event): QGraphicsScene.keyPressEvent(self, event) if event.key() == Qt.Key_F: if not self.insert_mode: self.velocity_mode = False self.insert_mode = True self.makeGhostNote(self.mousePos.x(), self.mousePos.y()) self.modeupdate.emit('insert_mode') elif self.insert_mode: self.insert_mode = False if self.place_ghost: self.place_ghost = False self.removeItem(self.ghost_note) self.ghost_note = None self.modeupdate.emit('') elif event.key() == Qt.Key_D: if self.velocity_mode: self.velocity_mode = False self.modeupdate.emit('') else: if self.insert_mode: self.removeItem(self.ghost_note) self.ghost_note = None self.insert_mode = False self.place_ghost = False self.velocity_mode = True self.modeupdate.emit('velocity_mode') elif event.key() == Qt.Key_A: if all((note.isSelected() for note in self.notes)): for note in self.notes: note.setSelected(False) self.selected_notes = [] else: for note in self.notes: note.setSelected(True) self.selected_notes = self.notes[:] elif event.key() in (Qt.Key_Delete, Qt.Key_Backspace): self.notes = [note for note in self.notes if note not in self.selected_notes] for note in self.selected_notes: self.removeItem(note) self.midievent.emit(["midievent-remove", note.note[0], note.note[1], note.note[2], note.note[3]]) del note self.selected_notes = [] def mousePressEvent(self, event): QGraphicsScene.mousePressEvent(self, event) if not (any(key.pressed for key in self.piano_keys) or any(note.pressed for note in self.notes)): for note in self.selected_notes: note.setSelected(False) self.selected_notes = [] if event.button() == Qt.LeftButton: if self.insert_mode: self.place_ghost = True else: self.marquee_select = True self.marquee_rect = QRectF(event.scenePos().x(), event.scenePos().y(), 1, 1) self.marquee = QGraphicsRectItem(self.marquee_rect) self.marquee.setBrush(QColor(255, 255, 255, 100)) self.addItem(self.marquee) else: for s_note in self.notes: if s_note.pressed and s_note in self.selected_notes: break elif s_note.pressed and s_note not in self.selected_notes: for note in self.selected_notes: note.setSelected(False) self.selected_notes = [s_note] break for note in self.selected_notes: if not self.velocity_mode: note.mousePressEvent(event) def mouseMoveEvent(self, event): QGraphicsScene.mouseMoveEvent(self, event) self.mousePos = event.scenePos() if not (any((key.pressed for key in self.piano_keys))): m_pos = event.scenePos() if self.insert_mode and self.place_ghost: #placing a note m_width = self.ghost_rect.x() + self.ghost_rect_orig_width if m_pos.x() > m_width: m_new_x = self.snap(m_pos.x()) self.ghost_rect.setRight(m_new_x) self.ghost_note.setRect(self.ghost_rect) #self.adjust_note_vel(event) else: m_pos = self.enforce_bounds(m_pos) if self.insert_mode: #ghostnote follows mouse around (m_new_x, m_new_y) = self.snap(m_pos.x(), m_pos.y()) self.ghost_rect.moveTo(m_new_x, m_new_y) try: self.ghost_note.setRect(self.ghost_rect) except RuntimeError: self.ghost_note = None self.makeGhostNote(m_new_x, m_new_y) elif self.marquee_select: marquee_orig_pos = event.buttonDownScenePos(Qt.LeftButton) if marquee_orig_pos.x() < m_pos.x() and marquee_orig_pos.y() < m_pos.y(): self.marquee_rect.setBottomRight(m_pos) elif marquee_orig_pos.x() < m_pos.x() and marquee_orig_pos.y() > m_pos.y(): self.marquee_rect.setTopRight(m_pos) elif marquee_orig_pos.x() > m_pos.x() and marquee_orig_pos.y() < m_pos.y(): self.marquee_rect.setBottomLeft(m_pos) elif marquee_orig_pos.x() > m_pos.x() and marquee_orig_pos.y() > m_pos.y(): self.marquee_rect.setTopLeft(m_pos) self.marquee.setRect(self.marquee_rect) self.selected_notes = [] for item in self.collidingItems(self.marquee): if item in self.notes: self.selected_notes.append(item) for note in self.notes: if note in self.selected_notes: note.setSelected(True) else: note.setSelected(False) elif self.velocity_mode: if Qt.LeftButton == event.buttons(): for note in self.selected_notes: note.updateVelocity(event) elif not self.marquee_select: #move selected if Qt.LeftButton == event.buttons(): x = y = False if any(note.back.stretch for note in self.selected_notes): x = True elif any(note.front.stretch for note in self.selected_notes): y = True for note in self.selected_notes: note.back.stretch = x note.front.stretch = y note.moveEvent(event) def mouseReleaseEvent(self, event): if not (any((key.pressed for key in self.piano_keys)) or any((note.pressed for note in self.notes))): if event.button() == Qt.LeftButton: if self.place_ghost and self.insert_mode: self.place_ghost = False note_start = self.get_note_start_from_x(self.ghost_rect.x()) note_num = self.get_note_num_from_y(self.ghost_rect.y()) note_length = self.get_note_length_from_x(self.ghost_rect.width()) self.drawNote(note_num, note_start, note_length, self.ghost_vel) self.midievent.emit(["midievent-add", note_num, note_start, note_length, self.ghost_vel]) self.makeGhostNote(self.mousePos.x(), self.mousePos.y()) elif self.marquee_select: self.marquee_select = False self.removeItem(self.marquee) elif not self.marquee_select: for note in self.selected_notes: old_info = note.note[:] note.mouseReleaseEvent(event) if self.velocity_mode: note.setSelected(True) if not old_info == note.note: self.midievent.emit(["midievent-remove", old_info[0], old_info[1], old_info[2], old_info[3]]) self.midievent.emit(["midievent-add", note.note[0], note.note[1], note.note[2], note.note[3]]) # ------------------------------------------------------------------------- # Internal Functions def drawHeader(self): self.header = QGraphicsRectItem(0, 0, self.grid_width, self.header_height) #self.header.setZValue(1.0) self.header.setPos(self.piano_width, 0) self.addItem(self.header) def drawPiano(self): piano_keys_width = self.piano_width - self.padding labels = ('B','Bb','A','Ab','G','Gb','F','E','Eb','D','Db','C') black_notes = (2,4,6,9,11) piano_label = QFont() piano_label.setPointSize(6) self.piano = QGraphicsRectItem(0, 0, piano_keys_width, self.piano_height) self.piano.setPos(0, self.header_height) self.addItem(self.piano) key = PianoKeyItem(piano_keys_width, self.note_height, self.piano) label = QGraphicsSimpleTextItem('C8', key) label.setPos(18, 1) label.setFont(piano_label) key.setBrush(QColor(255, 255, 255)) for i in range(self.end_octave - self.start_octave, self.start_octave - self.start_octave, -1): for j in range(self.notes_in_octave, 0, -1): if j in black_notes: key = PianoKeyItem(piano_keys_width/1.4, self.note_height, self.piano) key.setBrush(QColor(0, 0, 0)) key.setZValue(1.0) key.setPos(0, self.note_height * j + self.octave_height * (i - 1)) elif (j - 1) and (j + 1) in black_notes: key = PianoKeyItem(piano_keys_width, self.note_height * 2, self.piano) key.setBrush(QColor(255, 255, 255)) key.setPos(0, self.note_height * j + self.octave_height * (i - 1) - self.note_height/2.) elif (j - 1) in black_notes: key = PianoKeyItem(piano_keys_width, self.note_height * 3./2, self.piano) key.setBrush(QColor(255, 255, 255)) key.setPos(0, self.note_height * j + self.octave_height * (i - 1) - self.note_height/2.) elif (j + 1) in black_notes: key = PianoKeyItem(piano_keys_width, self.note_height * 3./2, self.piano) key.setBrush(QColor(255, 255, 255)) key.setPos(0, self.note_height * j + self.octave_height * (i - 1)) if j == 12: label = QGraphicsSimpleTextItem('{}{}'.format(labels[j - 1], self.end_octave - i), key ) label.setPos(18, 6) label.setFont(piano_label) self.piano_keys.append(key) def drawGrid(self): black_notes = [2,4,6,9,11] scale_bar = QGraphicsRectItem(0, 0, self.grid_width, self.note_height, self.piano) scale_bar.setPos(self.piano_width, 0) scale_bar.setBrush(QColor(100,100,100)) clearpen = QPen(QColor(0,0,0,0)) for i in range(self.end_octave - self.start_octave, self.start_octave - self.start_octave, -1): for j in range(self.notes_in_octave, 0, -1): scale_bar = QGraphicsRectItem(0, 0, self.grid_width, self.note_height, self.piano) scale_bar.setPos(self.piano_width, self.note_height * j + self.octave_height * (i - 1)) scale_bar.setPen(clearpen) if j not in black_notes: scale_bar.setBrush(QColor(120,120,120)) else: scale_bar.setBrush(QColor(100,100,100)) measure_pen = QPen(QColor(0, 0, 0, 120), 3) half_measure_pen = QPen(QColor(0, 0, 0, 40), 2) line_pen = QPen(QColor(0, 0, 0, 40)) for i in range(0, int(self.num_measures) + 1): measure = QGraphicsLineItem(0, 0, 0, self.piano_height + self.header_height - measure_pen.width(), self.header) measure.setPos(self.measure_width * i, 0.5 * measure_pen.width()) measure.setPen(measure_pen) if i < self.num_measures: number = QGraphicsSimpleTextItem('%d' % (i + 1), self.header) number.setPos(self.measure_width * i + 5, 2) number.setBrush(Qt.white) for j in self.frange(0, self.time_sig[0]*self.grid_div/self.time_sig[1], 1.): line = QGraphicsLineItem(0, 0, 0, self.piano_height, self.header) line.setZValue(1.0) line.setPos(self.measure_width * i + self.value_width * j, self.header_height) if j == self.time_sig[0]*self.grid_div/self.time_sig[1] / 2.0: line.setPen(half_measure_pen) else: line.setPen(line_pen) def drawPlayHead(self): self.play_head = QGraphicsLineItem(self.piano_width, self.header_height, self.piano_width, self.total_height) self.play_head.setPen(QPen(QColor(255,255,255,50), 2)) self.play_head.setZValue(1.) self.addItem(self.play_head) def refreshScene(self): list(map(self.removeItem, self.notes)) self.selected_notes = [] self.piano_keys = [] self.clear() self.drawPiano() self.drawHeader() self.drawGrid() self.drawPlayHead() for note in self.notes[:]: if note.note[1] >= (self.num_measures * self.time_sig[0]): self.notes.remove(note) self.midievent.emit(["midievent-remove", note.note[0], note.note[1], note.note[2], note.note[3]]) elif note.note[2] > self.max_note_length: new_note = note.note[:] new_note[2] = self.max_note_length self.notes.remove(note) self.drawNote(new_note[0], new_note[1], self.max_note_length, new_note[3], False) self.midievent.emit(["midievent-remove", note.note[0], note.note[1], note.note[2], note.note[3]]) self.midievent.emit(["midievent-add", new_note[0], new_note[1], new_note[2], new_note[3]]) list(map(self.addItem, self.notes)) if self.views(): self.views()[0].setSceneRect(self.itemsBoundingRect()) def clearNotes(self): self.clear() self.notes = [] self.selected_notes = [] self.drawPiano() self.drawHeader() self.drawGrid() def makeGhostNote(self, pos_x, pos_y): """creates the ghostnote that is placed on the scene before the real one is.""" if self.ghost_note: self.removeItem(self.ghost_note) length = self.full_note_width * self.default_length (start, note) = self.snap(pos_x, pos_y) self.ghost_vel = self.default_ghost_vel self.ghost_rect = QRectF(start, note, length, self.note_height) self.ghost_rect_orig_width = self.ghost_rect.width() self.ghost_note = QGraphicsRectItem(self.ghost_rect) self.ghost_note.setBrush(QColor(230, 221, 45, 100)) self.addItem(self.ghost_note) def drawNote(self, note_num, note_start=None, note_length=None, note_velocity=None, add=True): """ note_num: midi number, 0 - 127 note_start: 0 - (num_measures * time_sig[0]) so this is in beats note_length: 0 - (num_measures * time_sig[0]/time_sig[1]) this is in measures note_velocity: 0 - 127 """ info = [note_num, note_start, note_length, note_velocity] if not note_start % (self.num_measures * self.time_sig[0]) == note_start: #self.midievent.emit(["midievent-remove", note_num, note_start, note_length, note_velocity]) while not note_start % (self.num_measures * self.time_sig[0]) == note_start: self.setMeasures(self.num_measures+1) self.measureupdate.emit(self.num_measures) self.refreshScene() x_start = self.get_note_x_start(note_start) if note_length > self.max_note_length: note_length = self.max_note_length + 0.25 x_length = self.get_note_x_length(note_length) y_pos = self.get_note_y_pos(note_num) note = NoteItem(self.note_height, x_length, info) note.setPos(x_start, y_pos) self.notes.append(note) if add: self.addItem(note) # ------------------------------------------------------------------------- # Helper Functions def frange(self, x, y, t): while x < y: yield x x += t def quantize(self, value): self.snap_value = float(self.full_note_width) * value if value else None def snap(self, pos_x, pos_y = None): if self.snap_value: pos_x = int(round((pos_x - self.piano_width) / self.snap_value)) \ * self.snap_value + self.piano_width if pos_y: pos_y = int((pos_y - self.header_height) / self.note_height) \ * self.note_height + self.header_height return (pos_x, pos_y) if pos_y else pos_x def adjust_note_vel(self, event): m_pos = event.scenePos() #bind velocity to vertical mouse movement self.ghost_vel += (event.lastScenePos().y() - m_pos.y())/10 if self.ghost_vel < 0: self.ghost_vel = 0 elif self.ghost_vel > 127: self.ghost_vel = 127 m_width = self.ghost_rect.x() + self.ghost_rect_orig_width if m_pos.x() < m_width: m_pos.setX(m_width) m_new_x = self.snap(m_pos.x()) self.ghost_rect.setRight(m_new_x) self.ghost_note.setRect(self.ghost_rect) def enforce_bounds(self, pos): if pos.x() < self.piano_width: pos.setX(self.piano_width) elif pos.x() > self.grid_width + self.piano_width: pos.setX(self.grid_width + self.piano_width) if pos.y() < self.header_height + self.padding: pos.setY(self.header_height + self.padding) return pos def get_note_start_from_x(self, note_x): return (note_x - self.piano_width) / (self.grid_width / self.num_measures / self.time_sig[0]) def get_note_x_start(self, note_start): return self.piano_width + \ (self.grid_width / self.num_measures / self.time_sig[0]) * note_start def get_note_x_length(self, note_length): return float(self.time_sig[1]) / self.time_sig[0] * note_length * self.grid_width / self.num_measures def get_note_length_from_x(self, note_x): return float(self.time_sig[0]) / self.time_sig[1] * self.num_measures / self.grid_width \ * note_x def get_note_y_pos(self, note_num): return self.header_height + self.note_height * (self.total_notes - note_num - 1) def get_note_num_from_y(self, note_y_pos): return -(((note_y_pos - self.header_height) / self.note_height) - self.total_notes + 1)
class PreXoverItemGroup(QGraphicsEllipseItem): """Summary Attributes: active_wedge_gizmo (TYPE): Description fwd_prexover_items (dict): Description HUE_FACTOR (float): Description id_num (TYPE): Description is_active (TYPE): Description model_part (Part): The model part rev_prexover_items (dict): Description SPIRAL_FACTOR (float): Description virtual_helix_item (VirtualHelixItem): Description """ HUE_FACTOR = 1.6 SPIRAL_FACTOR = 0.4 def __init__(self, radius, rect, virtual_helix_item, is_active): """Summary Args: radius (TYPE): Description rect (TYPE): Description virtual_helix_item (VirtualHelixItem): Description is_active (TYPE): Description """ super(PreXoverItemGroup, self).__init__(rect, virtual_helix_item) self._radius = radius self._rect = rect self.virtual_helix_item = virtual_helix_item self.model_part = virtual_helix_item.part() self.id_num = virtual_helix_item.idNum() self.is_active = is_active self.active_wedge_gizmo = WedgeGizmo(radius, rect, self) self.fwd_prexover_items = fwd_pxis = {} self.rev_prexover_items = rev_pxis = {} self._colors = self._getColors() self.addItems() self.setPen(getNoPen()) z = styles.ZPXIGROUP + 10 if is_active else styles.ZPXIGROUP self.setZValue(z) self.setTransformOriginPoint(rect.center()) bpr, tpr, eulerZ = virtual_helix_item.getProperty(['bases_per_repeat', 'turns_per_repeat', 'eulerZ']) self.setRotation(-eulerZ) # add 180 # for baseNearestPoint fwd_pos, rev_pos = [], [] step_size = self.virtual_helix_item.getProperty('bases_per_repeat') for i in range(int(step_size)): fwd_pos.append((fwd_pxis[i].scenePos().x(), fwd_pxis[i].scenePos().y())) rev_pos.append((rev_pxis[i].scenePos().x(), rev_pxis[i].scenePos().y())) self.fwd_pos_array = np.asarray(fwd_pos) self.rev_pos_array = np.asarray(rev_pos) self.baseNearLine = QGraphicsLineItem(self) self.baseNearLine.setPen(getPenObj("#000000", 0.25, capstyle=Qt.RoundCap)) # end def def mousePressEvent(self, event): print("PreXoverGroup press") def mouseMoveEvent(self, event): print("PreXoverGroup move") def mouseReleaseEvent(self, event): print("PreXoverGroup release") ### ACCESSORS ### def partItem(self): """Summary Returns: TYPE: Description """ return self.virtual_helix_item.partItem() # end def def getItem(self, is_fwd, step_idx): """Summary Args: is_fwd (TYPE): Description step_idx (int): the base index within the virtual helix Returns: TYPE: Description """ items = self.fwd_prexover_items if is_fwd else self.rev_prexover_items if step_idx in items: return items[step_idx] else: return None # end def def getItemIdx(self, is_fwd, idx): """Summary Args: is_fwd (TYPE): Description idx (int): the base index within the virtual helix Returns: TYPE: Description """ step_size = self.virtual_helix_item.getProperty('bases_per_repeat') return self.getItem(is_fwd, idx % step_size) # end def ### EVENT HANDLERS ### ### PRIVATE SUPPORT METHODS ### def _getColors(self): """Summary Returns: TYPE: Description """ step_size = int(self.virtual_helix_item.getProperty('bases_per_repeat')) hue_scale = step_size*self.HUE_FACTOR return [QColor.fromHsvF(i / hue_scale, 0.75, 0.8).name() for i in range(step_size)] # end def ### PUBLIC SUPPORT METHODS ### def addItems(self): """Summary """ radius = self._radius step_size, bases_per_turn, tpb, mgroove = self.virtual_helix_item.getAngularProperties() # print("TPB", tpb, step_size) iw = PXI_PP_ITEM_WIDTH spiral_factor = self.SPIRAL_FACTOR colors = self._colors ctr = self.mapToParent(self._rect).boundingRect().center() x = ctr.x() + radius - PXI_PP_ITEM_WIDTH y = ctr.y() # tpb = -tpb # Qt +angle is Clockwise (CW), model +angle is CCW mgroove = -mgroove fwd_pxis = self.fwd_prexover_items rev_pxis = self.rev_prexover_items for i in range(int(step_size)): inset = i*spiral_factor # spiral layout fwd = PreXoverItem(i, tpb, step_size, colors[i], self, is_fwd=True) rev = PreXoverItem(i, tpb, step_size, colors[-1 - i], self, is_fwd=False) fwd.setPos(x - inset, y) rev.setPos(x - inset, y) fwd.setTransformOriginPoint((-radius + iw + inset), 0) rev.setTransformOriginPoint((-radius + iw + inset), 0) fwd.setRotation(round(i*tpb % 360, 3)) rev.setRotation(round((i*tpb + mgroove) % 360, 3)) fwd.setBondLineLength(inset + iw) rev.setBondLineLength(inset + iw) fwd_pxis[i] = fwd rev_pxis[i] = rev for i in range(int(step_size) - 1): fwd, next_fwd = fwd_pxis[i], fwd_pxis[i + 1] j = (step_size - 1) - i rev, next_rev = rev_pxis[j], rev_pxis[j - 1] fwd.set3pItem(next_fwd) rev.set3pItem(next_rev) next_fwd.set5pItem(fwd) next_rev.set5pItem(rev) # end def def baseNearestPoint(self, is_fwd, scene_pos): """Summary Args: is_fwd (bool): used to check fwd or rev lists. scene_pos (QPointF): scene coordinate position Returns: PreXoverItem: base nearest to position """ pos_array = self.fwd_pos_array if is_fwd else self.rev_pos_array dist_2 = np.sum((pos_array - (scene_pos.x(), scene_pos.y()))**2, axis=1) near_idx = np.argmin(dist_2) near_pxi = self.fwd_prexover_items[near_idx] if is_fwd else self.rev_prexover_items[near_idx] # Draw a line p1 = self.mapFromScene(scene_pos.x(), scene_pos.y()) p2 = self.mapFromScene(near_pxi.scenePos()) line = QLineF(p1, p2) self.baseNearLine.setLine(line) def destroyItem(self): """Summary """ fpxis = self.fwd_prexover_items rpxis = self.rev_prexover_items scene = self.scene() for i in range(len(fpxis)): x = fpxis.pop(i) x.destroyItem() x = rpxis.pop(i) x.destroyItem() self.virtual_helix_item = None self.model_part = None scene.removeItem(self.active_wedge_gizmo) self.active_wedge_gizmo = None scene.removeItem(self) # end def def updateTurnsPerRepeat(self): """Summary """ step_size, bases_per_turn, tpb, mgroove = self.virtual_helix_item.getAngularProperties() mgroove = -mgroove fpxis = self.fwd_prexover_items rpxis = self.rev_prexover_items for i in range(int(step_size)): fwd = self.fwd_prexover_items[i] rev = self.rev_prexover_items[i] fwd.setRotation(round((i*tpb) % 360, 3)) rev.setRotation(round((i*tpb + mgroove) % 360, 3)) for i in range(int(step_size) - 1): fwd, next_fwd = fpxis[i], fpxis[i + 1] j = (step_size - 1) - i rev, next_rev = rpxis[j], rpxis[j - 1] fwd.set3pItem(next_fwd) rev.set3pItem(next_rev) next_fwd.set5pItem(fwd) next_rev.set5pItem(rev) # end def def partCrossoverSpanAngle(self): """ Returns: int: Crossover span angle from Part. """ return self.virtual_helix_item.partCrossoverSpanAngle() def updateModelActiveBaseInfo(self, pre_xover_info): """Notify model of pre_xover_item hover state. """ self.model_part.setActiveBaseInfo(pre_xover_info)
class DiagramScene(QGraphicsScene): InsertItem, InsertLine, InsertText, MoveItem = range(4) itemInserted = pyqtSignal(DiagramItem) textInserted = pyqtSignal(QGraphicsTextItem) itemSelected = pyqtSignal(QGraphicsItem) def __init__(self, itemMenu, parent=None): super(DiagramScene, self).__init__(parent) self.myItemMenu = itemMenu self.myMode = self.MoveItem self.myItemType = DiagramItem.Step self.line = None self.textItem = None self.myItemColor = Qt.white self.myTextColor = Qt.black self.myLineColor = Qt.black self.myFont = QFont() def setLineColor(self, color): self.myLineColor = color if self.isItemChange(Arrow): item = self.selectedItems()[0] item.setColor(self.myLineColor) self.update() def setTextColor(self, color): self.myTextColor = color if self.isItemChange(DiagramTextItem): item = self.selectedItems()[0] item.setDefaultTextColor(self.myTextColor) def setItemColor(self, color): self.myItemColor = color if self.isItemChange(DiagramItem): item = self.selectedItems()[0] item.setBrush(self.myItemColor) def setFont(self, font): self.myFont = font if self.isItemChange(DiagramTextItem): item = self.selectedItems()[0] item.setFont(self.myFont) def setMode(self, mode): self.myMode = mode def setItemType(self, type): self.myItemType = type def editorLostFocus(self, item): cursor = item.textCursor() cursor.clearSelection() item.setTextCursor(cursor) if item.toPlainText(): self.removeItem(item) item.deleteLater() def mousePressEvent(self, mouseEvent): if (mouseEvent.button() != Qt.LeftButton): return if self.myMode == self.InsertItem: item = DiagramItem(self.myItemType, self.myItemMenu) item.setBrush(self.myItemColor) self.addItem(item) item.setPos(mouseEvent.scenePos()) self.itemInserted.emit(item) elif self.myMode == self.InsertLine: self.line = QGraphicsLineItem(QLineF(mouseEvent.scenePos(), mouseEvent.scenePos())) self.line.setPen(QPen(self.myLineColor, 2)) self.addItem(self.line) elif self.myMode == self.InsertText: textItem = DiagramTextItem() textItem.setFont(self.myFont) textItem.setTextInteractionFlags(Qt.TextEditorInteraction) textItem.setZValue(1000.0) textItem.lostFocus.connect(self.editorLostFocus) textItem.selectedChange.connect(self.itemSelected) self.addItem(textItem) textItem.setDefaultTextColor(self.myTextColor) textItem.setPos(mouseEvent.scenePos()) self.textInserted.emit(textItem) super(DiagramScene, self).mousePressEvent(mouseEvent) def mouseMoveEvent(self, mouseEvent): if self.myMode == self.InsertLine and self.line: newLine = QLineF(self.line.line().p1(), mouseEvent.scenePos()) self.line.setLine(newLine) elif self.myMode == self.MoveItem: super(DiagramScene, self).mouseMoveEvent(mouseEvent) def mouseReleaseEvent(self, mouseEvent): if self.line and self.myMode == self.InsertLine: startItems = self.items(self.line.line().p1()) if len(startItems) and startItems[0] == self.line: startItems.pop(0) endItems = self.items(self.line.line().p2()) if len(endItems) and endItems[0] == self.line: endItems.pop(0) self.removeItem(self.line) self.line = None if len(startItems) and len(endItems) and \ isinstance(startItems[0], DiagramItem) and \ isinstance(endItems[0], DiagramItem) and \ startItems[0] != endItems[0]: startItem = startItems[0] endItem = endItems[0] arrow = Arrow(startItem, endItem) arrow.setColor(self.myLineColor) startItem.addArrow(arrow) endItem.addArrow(arrow) arrow.setZValue(-1000.0) self.addItem(arrow) arrow.updatePosition() self.line = None super(DiagramScene, self).mouseReleaseEvent(mouseEvent) def isItemChange(self, type): for item in self.selectedItems(): if isinstance(item, type): return True return False
class DiagramScene(QGraphicsScene): InsertItem, InsertLine, InsertText, MoveItem, DefaultMode = range(5) itemInserted = pyqtSignal(int) textInserted = pyqtSignal(QGraphicsTextItem) itemSelected = pyqtSignal(QGraphicsItem) def __init__(self, item_menu, parent=None): super(DiagramScene, self).__init__(parent) self.my_item_menu = item_menu self.my_mode = self.DefaultMode self.my_item_type = "channel" self.line = None self.text_item = None self.my_item_color = Qt.white self.my_text_color = Qt.black self.my_line_color = Qt.black self.my_font = QFont() self.m_drag_offset = 0 self.m_dragged = None def set_line_color(self, color): self.my_line_color = color if self.is_item_changed(Arrow): item = self.selectedItems()[0] item.set_color(self.my_line_color) self.update() def set_text_color(self, color): self.my_text_color = color if self.is_item_changed(DiagramTextItem): item = self.selectedItems()[0] item.setDefaultTextColor(self.my_text_color) def set_item_color(self, color): self.my_item_color = color if self.is_item_changed(DiagramTextItem): item = self.selectedItems()[0] item.setBrush(self.my_item_color) def setFont(self, font): self.my_font = font if self.is_item_changed(DiagramTextItem): item = self.selectedItems()[0] item.setFont(self.my_font) def set_mode(self, mode): self.my_mode = mode def set_item_type(self, new_type): self.my_item_type = new_type def editor_lost_focus(self, item): if item: cursor = item.text_cursor() cursor.clearSelection() item.set_text_cursor(cursor) if item.to_plain_text(): self.removeItem(item) item.delete_later() # noinspection PyArgumentList def insert_item(self, item_type=None, x=None, y=None, text=None): if not text: text, ok = QInputDialog.getText(QInputDialog(), 'Insert name', 'Enter new object name:') if not ok: # TODO return item = FlumeObject(item_type, text).pictogram item.setBrush(self.my_item_color) self.addItem(item) item.setPos(x, y) return item def mousePressEvent(self, mouse_event): if mouse_event.button() != Qt.LeftButton: return if self.my_mode == self.InsertItem: x = mouse_event.scenePos().x() # // 50 * 50 y = mouse_event.scenePos().y() # // 50 * 50 item = self.insert_item(self.my_item_type, x, y) self.itemInserted.emit(item.flume_component) elif self.my_mode == self.InsertLine: self.line = QGraphicsLineItem(QLineF(mouse_event.scenePos(), mouse_event.scenePos())) self.line.setPen(QPen(self.my_line_color, 2)) self.addItem(self.line) elif self.my_mode == self.InsertText: text_item = DiagramTextItem() text_item.setFont(self.my_font) text_item.setTextInteractionFlags(Qt.TextEditorInteraction) text_item.setZValue(1000.0) text_item.lostFocus.connect(self.editor_lost_focus) # text_item.selectedChange.connect(self.itemSelected) self.addItem(text_item) text_item.setDefaultTextColor(self.my_text_color) text_item.setPos(mouse_event.scenePos()) self.textInserted.emit(text_item) else: self.m_dragged = QGraphicsScene.itemAt(self, mouse_event.scenePos(), QTransform()) if self.m_dragged: self.my_mode = self.MoveItem self.m_drag_offset = mouse_event.scenePos() - self.m_dragged.pos() super(DiagramScene, self).mousePressEvent(mouse_event) def mouseMoveEvent(self, mouse_event): if self.my_mode == self.InsertLine and self.line: new_line = QLineF(self.line.line().p1(), mouse_event.scenePos()) self.line.setLine(new_line) elif self.my_mode == self.MoveItem: if self.m_dragged: self.m_dragged.setPos(mouse_event.scenePos() - self.m_drag_offset) super(DiagramScene, self).mouseMoveEvent(mouse_event) def mouseReleaseEvent(self, mouse_event): if self.line and self.my_mode == self.InsertLine: start_items = self.items(self.line.line().p1()) if len(start_items) and start_items[0] == self.line: start_items.pop(0) end_items = self.items(self.line.line().p2()) if len(end_items) and end_items[0] == self.line: end_items.pop(0) self.removeItem(self.line) self.line = None if len(start_items) and len(end_items) and isinstance(start_items[0], FlumeDiagramItem) and \ isinstance(end_items[0], FlumeDiagramItem) and start_items[0] != end_items[0]: start_item = start_items[0] end_item = end_items[0] self.add_arrow(start_item, end_item) self.line = None if self.m_dragged: x = mouse_event.scenePos().x() # // 50 * 50 y = mouse_event.scenePos().y() # // 50 * 50 self.m_dragged.setPos(x, y) self.m_dragged = None self.my_mode = self.DefaultMode super(DiagramScene, self).mouseReleaseEvent(mouse_event) def add_arrow(self, start_item, end_item): arrow = Arrow(start_item, end_item) arrow.set_color(self.my_line_color) start_item.add_arrow(arrow) end_item.add_arrow(arrow) arrow.setZValue(-1000.0) self.addItem(arrow) arrow.update_position() def is_item_changed(self, new_type): for item in self.selectedItems(): if isinstance(item, new_type): return True return False
class RotaryDialHoverRegion(QGraphicsEllipseItem): def __init__(self, rect, parent=None): # setup DNA line super(QGraphicsEllipseItem, self).__init__(rect, parent) self._parent = parent self.setPen(QPen(Qt.NoPen)) self.setBrush(_HOVER_BRUSH) self.setAcceptHoverEvents(True) # hover marker self._hoverLine = QGraphicsLineItem(-_ROTARY_DELTA_WIDTH/2, 0, _ROTARY_DELTA_WIDTH/2, 0, self) self._hoverLine.setPen(QPen(QColor(204, 0, 0), .5)) self._hoverLine.hide() self._startPos = None self._startAngle = None # save selection start self._clockwise = None self.dummy = RotaryDialDeltaItem(0, 0, parent) self.dummy.hide() def updateRect(self, rect): self.setRect(rect) def hoverEnterEvent(self, event): self.updateHoverLine(event) self._hoverLine.show() # end def def hoverMoveEvent(self, event): self.updateHoverLine(event) # end def def hoverLeaveEvent(self, event): self._hoverLine.hide() # end def def mousePressEvent(self, event): r = _RADIUS self.updateHoverLine(event) pos = self._hoverLine.pos() aX, aY, angle = self.snapPosToCircle(pos, r) if angle != None: self._startPos = QPointF(aX, aY) self._startAngle = self.updateHoverLine(event) self.dummy.updateAngle(self._startAngle, 0) self.dummy.show() # mark the start # f = QGraphicsEllipseItem(pX, pY, 2, 2, self) # f.setPen(QPen(Qt.NoPen)) # f.setBrush(QBrush(QColor(204, 0, 0))) # end def def mouseMoveEvent(self, event): eventAngle = self.updateHoverLine(event) # Record initial direction before calling getSpanAngle if self._clockwise is None: self._clockwise = False if eventAngle > self._startAngle else True spanAngle = self.getSpanAngle(eventAngle) self.dummy.updateAngle(self._startAngle, spanAngle) # end def def mouseReleaseEvent(self, event): self.dummy.hide() endAngle = self.updateHoverLine(event) spanAngle = self.getSpanAngle(endAngle) old_angle = self._parent.virtualHelix().getProperty('eulerZ') new_angle = round((old_angle - spanAngle) % 360,0) self._parent.virtualHelix().setProperty('eulerZ', new_angle) # mark the end # x = self._hoverLine.x() # y = self._hoverLine.y() # f = QGraphicsEllipseItem(x, y, 6, 6, self) # f.setPen(QPen(Qt.NoPen)) # f.setBrush(QBrush(QColor(204, 0, 0, 128))) # end def def updateHoverLine(self, event): """ Moves red line to point (aX,aY) on RotaryDialLine closest to event.pos. Returns the angle of aX, aY, using the Qt arc coordinate system (0 = east, 90 = north, 180 = west, 270 = south). """ r = _RADIUS aX, aY, angle = self.snapPosToCircle(event.pos(), r) if angle != None: self._hoverLine.setPos(aX, aY) self._hoverLine.setRotation(-angle) return angle # end def def snapPosToCircle(self, pos, radius): """Given x, y and radius, return x,y of nearest point on circle, and its angle""" pX = pos.x() pY = pos.y() cX = cY = radius vX = pX - cX vY = pY - cY magV = sqrt(vX*vX + vY*vY) if magV == 0: return (None, None, None) aX = cX + vX / magV * radius aY = cY + vY / magV * radius angle = (atan2(aY-cY, aX-cX)) deg = -degrees(angle) if angle < 0 else 180+(180-degrees(angle)) return (aX, aY, deg) # end def def getSpanAngle(self, angle): """ Return the spanAngle angle by checking the initial direction of the selection. Selections that cross 0° must be handed as an edge case. """ if self._clockwise: # spanAngle is negative if angle < self._startAngle: spanAngle = angle - self._startAngle else: spanAngle = -(self._startAngle + (360-angle)) else: # counterclockwise, spanAngle is positive if angle > self._startAngle: spanAngle = angle - self._startAngle else: spanAngle = (360-self._startAngle) + angle return spanAngle