Пример #1
0
    def on_actItem_Polygon_triggered(self):  # 添加一个梯形

        item = QGraphicsPolygonItem()
        points = QPolygonF()

        points.append(QPointF(-40, -40))
        points.append(QPointF(40, -40))
        points.append(QPointF(100, 40))
        points.append(QPointF(-100, 40))

        item.setPolygon(points)
        item.setPos(-50 + (QtCore.qrand() % 100), -50 + (QtCore.qrand() % 100))

        item.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable)
        item.setBrush(QBrush(Qt.green))
        self.view.frontZ = self.view.frontZ + 1
        item.setZValue(self.view.frontZ)

        self.view.seqNum = self.view.seqNum + 1
        item.setData(self.view.ItemId, self.view.seqNum)  # //自定义数据,ItemId键
        item.setData(self.view.ItemDesciption, "梯形")

        self.scene.addItem(item)
        self.scene.clearSelection()
        item.setSelected(True)
Пример #2
0
 def on_qAction16_triggered(self):
     item = QGraphicsPolygonItem()
     points = [
         QPointF(-40, -40),
         QPointF(40, -40),
         QPointF(100, 40),
         QPointF(-100, 40)
     ]
     item.setPolygon(QPolygonF(points))
     item.setBrush(QBrush(Qt.green))
     self.__setItemProperties(item, "梯形")
Пример #3
0
class RPolygon(QObject):
    def __init__(self, points, color, line_width):
        self._points = [QPointF(p[0], p[1]) for p in points]
        self._pos = self._points[0]
        super().__init__()
        # The underlying QGraphicsPolygonItem
        self.polygon = QGraphicsPolygonItem()
        self.polygon.setPolygon(QPolygonF(self._points))
        self.polygon.setBrush(QtGui.QBrush(color))
        pen = QPen()
        pen.setWidthF(line_width)
        self.polygon.setPen(pen)
        self._visible = 1

    def x(self):
        return self._pos.x()

    def y(self):
        return self._pos.y()

    def points(self):
        return self._points

    # The following functions are for animation support

    @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._points = [
            QPointF(p.x() + delta_x,
                    p.y() + delta_y) for p in self._points
        ]
        self.polygon.setPolygon(QPolygonF(self._points))
        self._pos = value

    @pyqtProperty(int)
    def visible(self):
        return self._visible

    @visible.setter
    def visible(self, value):
        if (value > 0): self.polygon.show()
        else: self.polygon.hide()
        self._visible = value
Пример #4
0
    def create_ray_model(self, gscene, start_surf=1):
        tfrms = self.seq_model.compute_global_coords(start_surf)
        rayset = self.seq_model.trace_boundary_rays()

        start_offset = 0.1 * gscene.sceneRect().width()
        if abs(tfrms[0][1][2]) > start_offset:
            tfrms[0] = self.seq_model.shift_start_of_rayset(
                rayset, start_offset)

        pen = QPen()
        pen.setCosmetic(True)
        for rays in rayset:
            poly1 = []
            for i, r in enumerate(rays[3][0][0:]):
                rot, trns = tfrms[i]
                p = rot.dot(r[0]) + trns
                #                print(i, r[0], rot, trns, p)
                poly1.append(QPointF(p[2], -p[1]))

            poly2 = []
            for i, r in enumerate(rays[4][0][0:]):
                rot, trns = tfrms[i]
                p = rot.dot(r[0]) + trns
                #                print(i, r[0], rot, trns, p)
                poly2.append(QPointF(p[2], -p[1]))

            poly2.reverse()
            poly1.extend(poly2)
            polygon = QPolygonF()
            for p in poly1:
                polygon.append(p)
            gpoly = QGraphicsPolygonItem()
            gpoly.setPolygon(polygon)
            gpoly.setBrush(QColor(254, 197, 254, 64))  # magenta, 25%
            gpoly.setPen(pen)
            gscene.addItem(gpoly)
Пример #5
0
    def create_element_model(self, gscene):
        clut = rgbt.RGBTable(filename='gui/red_blue64.csv',
                             data_range=[10.0, 100.])
        ele_model = ele.ElementModel()
        ele_model.elements_from_sequence(self.seq_model)
        pen = QPen()
        pen.setCosmetic(True)
        for e in ele_model.elements:
            poly = e.shape()
            polygon = QPolygonF()
            for p in poly:
                polygon.append(QPointF(p[0], p[1]))
            gpoly = QGraphicsPolygonItem()
            gpoly.setPolygon(polygon)
            # set element color based on V-number
            gc = float(e.medium.glass_code())
            vnbr = round(100.0 * (gc - int(gc)), 3)
            ergb = clut.get_color(vnbr)
            gpoly.setBrush(QColor(*ergb))
            gpoly.setPen(pen)

            t = e.tfrm[1]
            gpoly.setPos(QPointF(t[2], -t[1]))
            gscene.addItem(gpoly)
Пример #6
0
 def on_actItem_Triangle_triggered(self):
    item=QGraphicsPolygonItem()
    points=[QPointF(0,-40), QPointF(60,40), QPointF(-60,40)]
    item.setPolygon(QPolygonF(points))
    item.setBrush(QBrush(Qt.magenta))  #设置填充颜色
    self.__setItemProperties(item,"三角形")
Пример #7
0
class GraphicLine(QGraphicsLineItem):
    """
    This class is a graphic line with an arrow which connects
    two blocks in the scene.

    Attributes
    ----------
    origin : QGraphicsRectItem
        Origin rect of the line.
    destination : QGraphicsRectItem
        Destination rect of the line.
    scene : QGraphicsScene
        Current drawing scene.
    brush : QBrush
        Brush to draw the arrow.
    pen : QPen
        Pen to draw the arrow.
    arrow_head : QGraphicsPolygonItem
        Final arrow of the line.
    arrow_size : int
        Size of the head of the arrow.
    dim_label : QGraphicsTextItem
        Text showing the dimensions of the edge.
    is_valid : bool
        Flag monitoring whether the connection is consistent.

    Methods
    ----------
    gen_endpoints(QRectF, QRectF)
        Returns the shortest connection between the two rects.
    draw_arrow()
        Draws the polygon for the arrow.
    set_valid(bool)
        Assign validity for this line.
    update_dims(tuple)
        Update the line dimensions.
    update_pos(QRectF)
        Update the line position given the new rect position.
    remove_self()
        Delete this line.

    """
    def __init__(self, origin: QGraphicsRectItem,
                 destination: QGraphicsRectItem, scene):
        super(GraphicLine, self).__init__()
        self.origin = origin
        self.destination = destination
        self.scene = scene

        # This flag confirms a legal connection
        self.is_valid = True

        # Get the four sides of the rects
        destination_lines = u.get_sides_of(
            self.destination.sceneBoundingRect())
        origin_lines = u.get_sides_of(self.origin.sceneBoundingRect())

        # Get the shortest edge between the two blocks
        self.setLine(self.gen_endpoints(origin_lines, destination_lines))

        self.brush = QBrush(QColor(style.GREY_0))
        self.pen = QPen(QColor(style.GREY_0))
        self.pen.setWidth(4)
        self.pen.setCapStyle(Qt.RoundCap)
        self.pen.setJoinStyle(Qt.RoundJoin)
        self.setPen(self.pen)

        # Dimensions labels
        self.dim_label = QGraphicsTextItem()
        self.dim_label.setZValue(6)
        self.scene.addItem(self.dim_label)

        # Arrow head
        self.arrow_head = QGraphicsPolygonItem()
        self.arrow_head.setPen(self.pen)
        self.arrow_head.setBrush(self.brush)
        self.arrow_size = 15.0

        self.draw_arrow()

    @staticmethod
    def gen_endpoints(origin_sides: dict, destination_sides: dict) -> QLineF:
        """
        This method finds the shortest path between two rectangles.

        Parameters
        ----------
        origin_sides : dict
            The dictionary {side_label: side_size} of the starting rect.
        destination_sides : dict
            The dictionary {side_label: side_size} of the ending rect.

        Returns
        ----------
        QLineF
            The shortest line.

        """

        # Init the line with the maximum possible value
        shortest_line = QLineF(-sys.maxsize / 2, -sys.maxsize / 2,
                               sys.maxsize / 2, sys.maxsize / 2)
        for o_side, origin_side in origin_sides.items():
            o_mid_x, o_mid_y = u.get_midpoint(o_side, origin_side)

            for d_side, destination_side in destination_sides.items():
                d_mid_x, d_mid_y = u.get_midpoint(d_side, destination_side)

                # Update line
                line = QLineF(o_mid_x, o_mid_y, d_mid_x, d_mid_y)
                if line.length() < shortest_line.length():
                    shortest_line = line

        return shortest_line

    def draw_arrow(self) -> None:
        """
        This method draws an arrow at the end of the line.

        """

        polygon_arrow_head = QPolygonF()

        # Compute the arrow angle
        angle = math.acos(self.line().dx() / self.line().length())
        angle = ((math.pi * 2) - angle)

        # Compute the direction where the arrow points (1 up, -1 down)
        arrow_direction = 1
        if math.asin(self.line().dy() / self.line().length()) < 0:
            arrow_direction = -1

        # First point of the arrow tail
        arrow_p1 = self.line().p2() - arrow_direction * QPointF(
            arrow_direction * math.sin(angle + math.pi / 2.5) *
            self.arrow_size,
            math.cos(angle + math.pi / 2.5) * self.arrow_size)
        # Second point of the arrow tail
        arrow_p2 = self.line().p2() - arrow_direction * QPointF(
            arrow_direction * math.sin(angle + math.pi - math.pi / 2.5) *
            self.arrow_size,
            math.cos(angle + math.pi - math.pi / 2.5) * self.arrow_size)

        # Third point is the line end
        polygon_arrow_head.append(self.line().p2())
        polygon_arrow_head.append(arrow_p2)
        polygon_arrow_head.append(arrow_p1)

        # Add the arrow to the scene
        self.arrow_head.setZValue(1)
        self.arrow_head.setParentItem(self)
        self.arrow_head.setPolygon(polygon_arrow_head)

    def set_valid(self, valid: bool) -> None:
        """
        This method changes the arrow style: if the connection 
        is not valid the arrow becomes red, otherwise it 
        remains grey with dimensions displayed. 
        
        Parameters
        ----------
        valid : bool
            New value for the legality flag.

        """

        if valid:
            self.is_valid = True
            self.pen.setColor(QColor(style.GREY_0))
            self.brush.setColor(QColor(style.GREY_0))
            self.dim_label.setVisible(False)
        else:
            self.is_valid = False
            self.pen.setColor(QColor(style.RED_2))
            self.brush.setColor(QColor(style.RED_2))

            if self.scene.is_dim_visible:
                self.dim_label.setVisible(True)

    def update_dims(self, dims: tuple) -> None:
        """
        This method updates the input & output dimensions.
        
        Parameters
        ----------
        dims : tuple
            The new dimensions to update.

        """

        self.dim_label.setHtml("<div style = 'background-color: " +
                               style.RED_2 +
                               "; color: white; font-family: consolas;'>" +
                               str(dims) + "</div>")
        self.dim_label.setPos(self.line().center())

    def update_pos(self, new_target: QRectF):
        """
        This method updates the line as it origin or its destination has
        changed location.

        Parameters
        ----------
        new_target : QRectF

        """

        if new_target == self.destination:
            self.destination = new_target
        elif new_target == self.origin:
            self.origin = new_target

        # Get the four sides of the rects
        destination_lines = u.get_sides_of(
            self.destination.sceneBoundingRect())
        origin_lines = u.get_sides_of(self.origin.sceneBoundingRect())

        # Get the shortest edge between the two blocks
        self.setLine(self.gen_endpoints(origin_lines, destination_lines))
        self.draw_arrow()
        self.dim_label.setPos(self.line().center())

    def remove_self(self) -> None:
        """
        The line is removed from the scene along with origin and destination
        pointers.

        """

        self.scene.removeItem(self)
        self.scene.edges.remove(self)
        self.scene.removeItem(self.dim_label)
        self.origin = None
        self.destination = None
Пример #8
0
class TransitionGraphicsItem(QGraphicsObject):
    # constant values
    SQUARE_SIDE = 10
    ARROW_SIZE = 12
    PEN_NORMAL_WIDTH = 1
    PEN_FOCUS_WIDTH = 3

    posChanged = pyqtSignal('QGraphicsItem')

    def __init__(self, data):
        super(QGraphicsObject, self).__init__()
        self.transitionData = data

        self.originLine = None
        self.destinationLine = None
        self.arrow = None
        self.textGraphics = None
        self.middleHandle = None

        self.graphicsOrigin = self.transitionData.origin.getGraphicsItem()
        self.graphicsDestination = self.transitionData.destination.getGraphicsItem()

        # connect position changed event
        self.graphicsOrigin.posChanged.connect(self.statePosChanged)
        self.graphicsDestination.posChanged.connect(self.statePosChanged)

        self.midPointX = (self.graphicsDestination.scenePos().x() + self.graphicsOrigin.scenePos().x()) / 2.0
        self.midPointY = (self.graphicsDestination.scenePos().y() + self.graphicsOrigin.scenePos().y()) / 2.0

        self.createOriginLine()
        self.createDestinationLine()

        self.createArrow()
        self.createMiddleHandle()
        self.createIdTextBox()

    def statePosChanged(self, state):
        if self.graphicsOrigin == state:
            self.createOriginLine()
        elif self.graphicsDestination == state:
            self.createDestinationLine()
            self.createArrow()

    def createOriginLine(self):
        if self.originLine == None:
            self.originLine = QGraphicsLineItem(self.midPointX, self.midPointY, self.graphicsOrigin.scenePos().x(),
                                                self.graphicsOrigin.scenePos().y(), self)
        else:
            self.originLine.setLine(QLineF(self.midPointX, self.midPointY, self.graphicsOrigin.scenePos().x(),
                                           self.graphicsOrigin.scenePos().y()))
        myLine = self.originLine.line()
        myLine.setLength(myLine.length() - StateGraphicsItem.NODE_WIDTH / 2)
        self.originLine.setLine(myLine)

    def createDestinationLine(self):
        if self.destinationLine == None:
            self.destinationLine = QGraphicsLineItem(self.midPointX, self.midPointY, self.graphicsDestination.scenePos().x(),
                                                     self.graphicsDestination.scenePos().y(), self)
        else:
            self.destinationLine.setLine(QLineF(self.midPointX, self.midPointY, self.graphicsDestination.scenePos().x(),
                                                self.graphicsDestination.scenePos().y()))

        myLine = self.destinationLine.line()
        myLine.setLength(myLine.length() - StateGraphicsItem.NODE_WIDTH / 2)
        self.destinationLine.setLine(myLine)

    def createArrow(self):
        # add an arrow to destination line
        myLine = self.destinationLine.line()
        myLine.setLength(myLine.length() - TransitionGraphicsItem.ARROW_SIZE)
        rotatePoint = myLine.p2() - self.destinationLine.line().p2()

        rightPointX = rotatePoint.x() * math.cos(math.pi / 6) - rotatePoint.y() * math.sin(math.pi / 6)
        rightPointY = rotatePoint.x() * math.sin(math.pi / 6) + rotatePoint.y() * math.cos(math.pi / 6)
        rightPoint = QPointF(rightPointX + self.destinationLine.line().x2(),
                             rightPointY + self.destinationLine.line().y2())

        leftPointX = rotatePoint.x() * math.cos(-math.pi / 6) - rotatePoint.y() * math.sin(-math.pi / 6)
        leftPointY = rotatePoint.x() * math.sin(-math.pi / 6) + rotatePoint.y() * math.cos(-math.pi / 6)
        leftPoint = QPointF(leftPointX + self.destinationLine.line().x2(),
                            leftPointY + self.destinationLine.line().y2())

        polygon = QPolygonF()
        polygon << rightPoint << leftPoint << self.destinationLine.line().p2() << rightPoint

        if self.arrow == None:
            self.arrow = QGraphicsPolygonItem(polygon, self)
        else:
            self.arrow.setPolygon(polygon)

        brush = QBrush(Qt.SolidPattern)
        brush.setColor(Qt.black)
        self.arrow.setBrush(brush)

    def createMiddleHandle(self):
        # create middle handle
        if self.middleHandle == None:
            self.middleHandle = RectHandleGraphicsItem(TransitionGraphicsItem.SQUARE_SIDE, self)
            self.middleHandle.setFlag(QGraphicsItem.ItemIsMovable)

        self.middleHandle.setPos(self.midPointX, self.midPointY)

    def createIdTextBox(self):
        if self.textGraphics == None:
            self.textGraphics = IdTextBoxGraphicsItem(self.transitionData.name, self)
            self.textGraphics.textChanged.connect(self.nameChanged)
        else:
            self.textGraphics.setPlainText(self.transitionData.name)
        textWidth = self.textGraphics.boundingRect().width()
        self.textGraphics.setPos(self.midPointX - textWidth / 2, self.midPointY + TransitionGraphicsItem.SQUARE_SIDE -
                                 (TransitionGraphicsItem.SQUARE_SIDE / 2) + 5)

    def updateMiddlePoints(self, newPosition):
        self.midPointX = newPosition.x()
        self.midPointY = newPosition.y()
        self.createOriginLine()
        self.createDestinationLine()
        self.createArrow()
        self.createIdTextBox()
        self.posChanged.emit(self)

    def nameChanged(self, name):
        self.transitionData.name = name
        self.createIdTextBox()

    def boundingRect(self):
        if self.middleHandle != None:
            return self.middleHandle.boundingRect()
        else:
            return None

    def disableInteraction(self):
        if self.middleHandle is not None:
            self.middleHandle.setFlag(QGraphicsItem.ItemIsMovable, False)
            self.middleHandle.disableInteraction()
Пример #9
0
class NozzlePreviewWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.ui = Ui_NozzlePreview()
        self.ui.setupUi(self)

        self.brush = QBrush()
        self.brush.setStyle(1)
        self.scene = QGraphicsScene(self)
        self.upper = QGraphicsPolygonItem()
        self.lower = QGraphicsPolygonItem()
        self.upper.setBrush(self.brush)
        self.lower.setBrush(self.brush)
        self.scene.addItem(self.upper)
        self.scene.addItem(self.lower)
        self.ui.tabCrossSection.setScene(self.scene)

        self.ui.tabWidget.currentChanged.connect(self.rescale)

    def loadNozzle(self, nozzle):
        geomAlerts = nozzle.getGeometryErrors()

        self.ui.tabAlerts.clear()
        for err in geomAlerts:
            self.ui.tabAlerts.addItem(err.description)

        self.upper.setPolygon(QPolygonF([]))
        self.lower.setPolygon(QPolygonF([]))

        for alert in geomAlerts:
            if alert.level == motorlib.simResult.SimAlertLevel.ERROR:
                return

        convAngle = radians(nozzle.props['convAngle'].getValue())
        throatLen = nozzle.props['throatLength'].getValue()
        throatRad = nozzle.props['throat'].getValue() / 2
        divAngle = radians(nozzle.props['divAngle'].getValue())
        exitRad = nozzle.props['exit'].getValue() / 2
        outerRad = 1.25 * exitRad
        if QApplication.instance() and QApplication.instance(
        ).fileManager:  # Check if the app exists and has a fm
            motor = QApplication.instance().fileManager.getCurrentMotor()
            if len(motor.grains) > 0:
                outerRad = motor.grains[0].getProperty('diameter') / 2

        scale = 100 / nozzle.props['exit'].getValue()
        radDiff = exitRad - throatRad
        if divAngle != 0:
            divLen = radDiff / tan(divAngle)
        else:
            divLen = 0
        if convAngle != 0:
            convLen = (outerRad - throatRad) / tan(convAngle)
        else:
            convLen = 0
        upperPoints = [
            [throatLen, throatRad],
            [0, throatRad],
            [-divLen, exitRad],
            [-divLen, outerRad],
            [throatLen + convLen, outerRad],
        ]
        lower = QPolygonF(
            [QPointF(p[0] * scale, p[1] * scale) for p in upperPoints])
        upper = QPolygonF(
            [QPointF(p[0] * scale, -p[1] * scale) for p in upperPoints])

        self.upper.setPolygon(upper)
        self.lower.setPolygon(lower)
        self.rescale()

    def rescale(self):
        self.scene.setSceneRect(self.scene.itemsBoundingRect())
        self.ui.tabCrossSection.fitInView(self.scene.sceneRect(),
                                          Qt.KeepAspectRatio)
Пример #10
0
class EdgeItem(GraphItem):

    _qt_pen_styles = {
        'dashed': Qt.DashLine,
        'dotted': Qt.DotLine,
        'solid': Qt.SolidLine,
    }

    def __init__(self,
                 highlight_level,
                 spline,
                 label_center,
                 label,
                 from_node,
                 to_node,
                 parent=None,
                 penwidth=1,
                 edge_color=None,
                 style='solid'):
        super(EdgeItem, self).__init__(highlight_level, parent)

        self.from_node = from_node
        self.from_node.add_outgoing_edge(self)
        self.to_node = to_node
        self.to_node.add_incoming_edge(self)

        self._default_edge_color = self._COLOR_BLACK
        if edge_color is not None:
            self._default_edge_color = edge_color

        self._default_text_color = self._COLOR_BLACK
        self._default_color = self._COLOR_BLACK
        self._text_brush = QBrush(self._default_color)
        self._shape_brush = QBrush(self._default_color)
        if style in ['dashed', 'dotted']:
            self._shape_brush = QBrush(Qt.transparent)
        self._label_pen = QPen()
        self._label_pen.setColor(self._default_text_color)
        self._label_pen.setJoinStyle(Qt.RoundJoin)
        self._edge_pen = QPen(self._label_pen)
        self._edge_pen.setWidth(penwidth)
        self._edge_pen.setColor(self._default_edge_color)
        self._edge_pen.setStyle(self._qt_pen_styles.get(style, Qt.SolidLine))

        self._sibling_edges = set()

        self._label = None
        if label is not None:
            self._label = QGraphicsSimpleTextItem(label)
            self._label.setFont(GraphItem._LABEL_FONT)
            label_rect = self._label.boundingRect()
            label_rect.moveCenter(label_center)
            self._label.setPos(label_rect.x(), label_rect.y())
            self._label.hoverEnterEvent = self._handle_hoverEnterEvent
            self._label.hoverLeaveEvent = self._handle_hoverLeaveEvent
            self._label.setAcceptHoverEvents(True)

        # spline specification according to
        # http://www.graphviz.org/doc/info/attrs.html#k:splineType
        coordinates = spline.split(' ')
        # extract optional end_point
        end_point = None
        if (coordinates[0].startswith('e,')):
            parts = coordinates.pop(0)[2:].split(',')
            end_point = QPointF(float(parts[0]), -float(parts[1]))
        # extract optional start_point
        if (coordinates[0].startswith('s,')):
            parts = coordinates.pop(0).split(',')

        # first point
        parts = coordinates.pop(0).split(',')
        point = QPointF(float(parts[0]), -float(parts[1]))
        path = QPainterPath(point)

        while len(coordinates) > 2:
            # extract triple of points for a cubic spline
            parts = coordinates.pop(0).split(',')
            point1 = QPointF(float(parts[0]), -float(parts[1]))
            parts = coordinates.pop(0).split(',')
            point2 = QPointF(float(parts[0]), -float(parts[1]))
            parts = coordinates.pop(0).split(',')
            point3 = QPointF(float(parts[0]), -float(parts[1]))
            path.cubicTo(point1, point2, point3)

        self._arrow = None
        if end_point is not None:
            # draw arrow
            self._arrow = QGraphicsPolygonItem()
            polygon = QPolygonF()
            polygon.append(point3)
            offset = QPointF(end_point - point3)
            corner1 = QPointF(-offset.y(), offset.x()) * 0.35
            corner2 = QPointF(offset.y(), -offset.x()) * 0.35
            polygon.append(point3 + corner1)
            polygon.append(end_point)
            polygon.append(point3 + corner2)
            self._arrow.setPolygon(polygon)
            self._arrow.hoverEnterEvent = self._handle_hoverEnterEvent
            self._arrow.hoverLeaveEvent = self._handle_hoverLeaveEvent
            self._arrow.setAcceptHoverEvents(True)

        self._path = QGraphicsPathItem(parent)
        self._path.setPath(path)
        self.addToGroup(self._path)

        self.set_node_color()
        self.set_label_color()

    def add_to_scene(self, scene):
        scene.addItem(self)
        if self._label is not None:
            scene.addItem(self._label)
        if self._arrow is not None:
            scene.addItem(self._arrow)

    def setToolTip(self, tool_tip):
        super(EdgeItem, self).setToolTip(tool_tip)
        if self._label is not None:
            self._label.setToolTip(tool_tip)
        if self._arrow is not None:
            self._arrow.setToolTip(tool_tip)

    def add_sibling_edge(self, edge):
        self._sibling_edges.add(edge)

    def set_node_color(self, color=None):
        if color is None:
            self._label_pen.setColor(self._default_text_color)
            self._text_brush.setColor(self._default_color)
            if self._shape_brush.isOpaque():
                self._shape_brush.setColor(self._default_edge_color)
            self._edge_pen.setColor(self._default_edge_color)
        else:
            self._label_pen.setColor(color)
            self._text_brush.setColor(color)
            if self._shape_brush.isOpaque():
                self._shape_brush.setColor(color)
            self._edge_pen.setColor(color)

        self._path.setPen(self._edge_pen)
        if self._arrow is not None:
            self._arrow.setBrush(self._shape_brush)
            self._arrow.setPen(self._edge_pen)

    def set_label_color(self, color=None):
        if color is None:
            self._label_pen.setColor(self._default_text_color)
        else:
            self._label_pen.setColor(color)

        if self._label is not None:
            self._label.setBrush(self._text_brush)
            self._label.setPen(self._label_pen)

    def _handle_hoverEnterEvent(self, event):
        # hovered edge item in red
        self.set_node_color(self._COLOR_RED)
        self.set_label_color(self._COLOR_RED)

        if self._highlight_level > 1:
            if self.from_node != self.to_node:
                # from-node in blue
                self.from_node.set_node_color(self._COLOR_BLUE)
                # to-node in green
                self.to_node.set_node_color(self._COLOR_GREEN)
            else:
                # from-node/in-node in teal
                self.from_node.set_node_color(self._COLOR_TEAL)
                self.to_node.set_node_color(self._COLOR_TEAL)
        if self._highlight_level > 2:
            # sibling edges in orange
            for sibling_edge in self._sibling_edges:
                sibling_edge.set_node_color(self._COLOR_ORANGE)

    def _handle_hoverLeaveEvent(self, event):
        self.set_node_color()
        self.set_label_color()
        if self._highlight_level > 1:
            self.from_node.set_node_color()
            self.to_node.set_node_color()
        if self._highlight_level > 2:
            for sibling_edge in self._sibling_edges:
                sibling_edge.set_node_color()
Пример #11
0
class ASCGraphicsView(QGraphicsView):
    scale_signal = pyqtSignal('float', 'float')
    set_focus_point_signal = pyqtSignal('int', 'int', 'int')
    set_focus_point_percent_signal = pyqtSignal('float', 'float', 'float')
    move_focus_point_signal = pyqtSignal('int', 'int', 'int')
    # x, y, z, BRUSH_TYPE, BRUSH_SIZE, ERASE
    paint_anno_on_point_signal = pyqtSignal('int', 'int', 'int', 'int', 'int',
                                            'bool', 'bool')

    def __init__(self, parent=None):
        super(ASCGraphicsView, self).__init__(parent)
        self.scene = QGraphicsScene(self)

        self.raw_img_item = QGraphicsPixmapItem()
        self.raw_img_item.setZValue(0)
        self.anno_img_item = QGraphicsPixmapItem()
        self.anno_img_item.setZValue(1)

        self.cross_bar_v_line_item = QGraphicsLineItem()
        self.cross_bar_h_line_item = QGraphicsLineItem()
        self.cross_bar_v_line_item.setZValue(100)
        self.cross_bar_h_line_item.setZValue(100)
        self.cross_bar_v_line_item.setPen(
            QPen(Qt.blue, 0, Qt.DotLine, Qt.FlatCap, Qt.RoundJoin))
        self.cross_bar_h_line_item.setPen(
            QPen(Qt.blue, 0, Qt.DotLine, Qt.FlatCap, Qt.RoundJoin))

        self.paint_brush_circle_item = QGraphicsEllipseItem()
        self.paint_brush_rect_item = QGraphicsPolygonItem()
        self.paint_brush_circle_item.setZValue(10)
        self.paint_brush_rect_item.setZValue(11)
        self.paint_brush_circle_item.setVisible(False)
        self.paint_brush_rect_item.setVisible(False)
        self.paint_brush_circle_item.setPen(
            QPen(Qt.red, 0, Qt.DotLine, Qt.FlatCap, Qt.RoundJoin))
        self.paint_brush_rect_item.setPen(
            QPen(Qt.red, 0, Qt.DotLine, Qt.FlatCap, Qt.RoundJoin))

        self.scene.addItem(self.raw_img_item)
        self.scene.addItem(self.anno_img_item)
        self.scene.addItem(self.cross_bar_v_line_item)
        self.scene.addItem(self.cross_bar_h_line_item)
        self.scene.addItem(self.paint_brush_circle_item)
        self.scene.addItem(self.paint_brush_rect_item)

        self.setScene(self.scene)
        self.setViewport(QOpenGLWidget())

        self._last_button_press = Qt.NoButton
        self._last_pos_middle_button = None
        self._last_pos_right_button = None

        self._brush_stats = {'type': BRUSH_TYPE_NO_BRUSH, 'size': 5}

        self.setResizeAnchor(QGraphicsView.AnchorViewCenter)

        self.slice_scroll_bar = None
        self.image_size = None
        self.is_valid = False

    def clear(self):
        """before loading new image"""
        self._last_pos_middle_button = None
        self._last_pos_right_button = None
        self._last_button_press = Qt.NoButton
        self.raw_img_item.setPixmap(QPixmap())
        self.anno_img_item.setPixmap(QPixmap())
        self.paint_brush_circle_item.setVisible(False)
        self.paint_brush_rect_item.setVisible(False)
        self.image_size = None
        self.is_valid = False

    def init_view(self, image_size):
        """after loading new image"""
        self.is_valid = True
        self.image_size = image_size
        self.slice_scroll_bar = self.parent().findChild(
            QScrollBar,
            self.objectName()[0] + 'SliceScrollBar')

        trans_mat = item2scene_transform[self.objectName()[0]]
        self.raw_img_item.setTransform(trans_mat)
        self.anno_img_item.setTransform(trans_mat)
        self.cross_bar_v_line_item.setTransform(trans_mat)
        self.cross_bar_h_line_item.setTransform(trans_mat)
        self.paint_brush_rect_item.setTransform(trans_mat)
        self.paint_brush_circle_item.setTransform(trans_mat)

        self.fitInView(self.raw_img_item, Qt.KeepAspectRatio)
        self.paint_brush_circle_item.setVisible(False)
        self.paint_brush_rect_item.setVisible(False)

    @property
    def brush_stats(self):
        return self._brush_stats

    @brush_stats.setter
    def brush_stats(self, stats_tuple):
        b_type, size = stats_tuple
        if b_type in [
                BRUSH_TYPE_NO_BRUSH, BRUSH_TYPE_CIRCLE_BRUSH,
                BRUSH_TYPE_RECT_BRUSH
        ]:
            self._brush_stats['type'] = b_type
            self._brush_stats['size'] = size
        if b_type != BRUSH_TYPE_NO_BRUSH:
            self.setMouseTracking(True)
        else:
            self.setMouseTracking(False)

    def update_brush_preview(self, x, y, out_of_sight=False):
        if not self.is_valid or self.brush_stats[
                'type'] == BRUSH_TYPE_NO_BRUSH or out_of_sight:
            self.paint_brush_rect_item.setVisible(False)
            self.paint_brush_circle_item.setVisible(False)
            return

        center = self.anno_img_item.mapFromScene(self.mapToScene(x, y))

        start_x = self.raw_img_item.boundingRect().topLeft().x()
        start_y = self.raw_img_item.boundingRect().topLeft().y()
        end_x = self.raw_img_item.boundingRect().bottomRight().x()
        end_y = self.raw_img_item.boundingRect().bottomRight().y()
        center.setX(min(max(start_x, center.x()), end_x) + 0.5)
        center.setY(min(max(start_y, center.y()), end_y) + 0.5)
        top_left_x = int(center.x() - self.brush_stats['size'] / 2)
        top_left_y = int(center.y() - self.brush_stats['size'] / 2)
        rect = QRectF(top_left_x, top_left_y, self.brush_stats['size'],
                      self.brush_stats['size'])
        if self.brush_stats['type'] == BRUSH_TYPE_CIRCLE_BRUSH:
            self.paint_brush_rect_item.setVisible(False)
            self.paint_brush_circle_item.setVisible(True)
            self.paint_brush_circle_item.setRect(rect)
        if self.brush_stats['type'] == BRUSH_TYPE_RECT_BRUSH:
            self.paint_brush_rect_item.setVisible(True)
            self.paint_brush_circle_item.setVisible(False)
            self.paint_brush_rect_item.setPolygon(QPolygonF(rect))

    def anno_paint(self, x, y, erase=False, new_step=False):
        pos_on_item = self.raw_img_item.mapFromScene(self.mapToScene(x, y))
        if self.objectName() == 'aGraphicsView':
            paint_point = [pos_on_item.y(), pos_on_item.x(), 999999]
        if self.objectName() == 'sGraphicsView':
            paint_point = [999999, pos_on_item.y(), pos_on_item.x()]
        if self.objectName() == 'cGraphicsView':
            paint_point = [pos_on_item.y(), 999999, pos_on_item.x()]
        self.paint_anno_on_point_signal.emit(math.floor(paint_point[0]),
                                             math.floor(paint_point[1]),
                                             math.floor(paint_point[2]),
                                             self.brush_stats['type'],
                                             self.brush_stats['size'], erase,
                                             new_step)

    @pyqtSlot('int')
    def on_slice_scroll_bar_changed(self, value):
        if not self.is_valid:
            return
        ratios = [-1, -1, -1]
        ratio = (value - self.slice_scroll_bar.minimum()) / \
                (self.slice_scroll_bar.maximum() - self.slice_scroll_bar.minimum())
        if self.objectName() == 'aGraphicsView':
            ratios[2] = ratio
        if self.objectName() == 'sGraphicsView':
            ratios[0] = ratio
        if self.objectName() == 'cGraphicsView':
            ratios[1] = ratio
        self.set_focus_point_percent_signal.emit(ratios[0], ratios[1],
                                                 ratios[2])

    @pyqtSlot('int', 'int')
    def set_brush_stats(self, b_type, size):
        self.brush_stats = [b_type, size]

    @pyqtSlot('int', 'int', 'int')
    def set_cross_bar(self, x, y, z):
        if self.objectName() == 'aGraphicsView':
            cross_bar_x = y
            cross_bar_y = x
            slice_bar_ratio = z / self.image_size[2]
        if self.objectName() == 'sGraphicsView':
            cross_bar_x = z
            cross_bar_y = y
            slice_bar_ratio = x / self.image_size[0]
        if self.objectName() == 'cGraphicsView':
            cross_bar_x = z
            cross_bar_y = x
            slice_bar_ratio = y / self.image_size[1]
        # cross line in voxel center
        cross_bar_x = cross_bar_x + 0.5
        cross_bar_y = cross_bar_y + 0.5
        start_x = self.raw_img_item.boundingRect().topLeft().x()
        start_y = self.raw_img_item.boundingRect().topLeft().y()
        end_x = self.raw_img_item.boundingRect().bottomRight().x()
        end_y = self.raw_img_item.boundingRect().bottomRight().y()
        self.cross_bar_v_line_item.setLine(cross_bar_x, start_y, cross_bar_x,
                                           end_y)
        self.cross_bar_h_line_item.setLine(start_x, cross_bar_y, end_x,
                                           cross_bar_y)

        slice_bar_value = round(slice_bar_ratio * (self.slice_scroll_bar.maximum() - self.slice_scroll_bar.minimum())) \
                          + self.slice_scroll_bar.minimum()
        self.slice_scroll_bar.setValue(slice_bar_value)

    def mousePressEvent(self, event: QtGui.QMouseEvent):
        self._last_button_press = event.button()

        if self.brush_stats['type'] == BRUSH_TYPE_NO_BRUSH:
            if event.button() == Qt.LeftButton:
                item_coord_pos = self.raw_img_item.mapFromScene(
                    self.mapToScene(event.pos()))
                if self.objectName() == 'aGraphicsView':
                    new_focus_point = [
                        item_coord_pos.y(),
                        item_coord_pos.x(), 999999
                    ]
                if self.objectName() == 'sGraphicsView':
                    new_focus_point = [
                        999999, item_coord_pos.y(),
                        item_coord_pos.x()
                    ]
                if self.objectName() == 'cGraphicsView':
                    new_focus_point = [
                        item_coord_pos.y(), 999999,
                        item_coord_pos.x()
                    ]
                self.set_focus_point_signal.emit(
                    math.floor(new_focus_point[0]),
                    math.floor(new_focus_point[1]),
                    math.floor(new_focus_point[2]))
            elif event.button() == Qt.MiddleButton:
                self._last_pos_middle_button = event.pos()
                self.setCursor(Qt.ClosedHandCursor)
            elif event.button() == Qt.RightButton:
                self._last_pos_right_button = event.pos()
            else:
                super(ASCGraphicsView, self).mousePressEvent(event)
        if self.brush_stats['type'] in [
                BRUSH_TYPE_CIRCLE_BRUSH, BRUSH_TYPE_RECT_BRUSH
        ]:
            if event.button() == Qt.LeftButton:
                self.anno_paint(event.x(),
                                event.y(),
                                erase=False,
                                new_step=True)
            elif event.button() == Qt.MiddleButton:
                self._last_pos_middle_button = event.pos()
                self.setCursor(Qt.ClosedHandCursor)
            elif event.button() == Qt.RightButton:
                self.anno_paint(event.x(),
                                event.y(),
                                erase=True,
                                new_step=True)

    def mouseMoveEvent(self, event: QtGui.QMouseEvent):
        if self.brush_stats['type'] == BRUSH_TYPE_NO_BRUSH:
            if self._last_button_press == Qt.LeftButton:
                item_coord_pos = self.raw_img_item.mapFromScene(
                    self.mapToScene(event.pos()))
                if self.objectName() == 'aGraphicsView':
                    new_focus_point = [
                        item_coord_pos.y(),
                        item_coord_pos.x(), 999999
                    ]
                if self.objectName() == 'sGraphicsView':
                    new_focus_point = [
                        999999, item_coord_pos.y(),
                        item_coord_pos.x()
                    ]
                if self.objectName() == 'cGraphicsView':
                    new_focus_point = [
                        item_coord_pos.y(), 999999,
                        item_coord_pos.x()
                    ]
                self.set_focus_point_signal.emit(
                    math.floor(new_focus_point[0]),
                    math.floor(new_focus_point[1]),
                    math.floor(new_focus_point[2]))
            elif self._last_button_press == Qt.MiddleButton:
                delta_x = event.x() - self._last_pos_middle_button.x()
                delta_y = event.y() - self._last_pos_middle_button.y()
                self.horizontalScrollBar().setValue(
                    self.horizontalScrollBar().value() - delta_x)
                self.verticalScrollBar().setValue(
                    self.verticalScrollBar().value() - delta_y)
                self._last_pos_middle_button = event.pos()
            elif self._last_button_press == Qt.RightButton:
                delta = event.pos().y() - self._last_pos_right_button.y()
                scale = 1 - float(delta) / float(self.size().height())
                self.scale_signal.emit(scale, scale)
                self._last_pos_right_button = event.pos()
            else:
                super(ASCGraphicsView, self).mouseMoveEvent(event)
        if self.brush_stats['type'] in [
                BRUSH_TYPE_CIRCLE_BRUSH, BRUSH_TYPE_RECT_BRUSH
        ]:
            self.update_brush_preview(event.x(), event.y())
            if self._last_button_press == Qt.LeftButton:
                self.anno_paint(event.x(),
                                event.y(),
                                erase=False,
                                new_step=False)
            elif self._last_button_press == Qt.MiddleButton:
                delta_x = event.x() - self._last_pos_middle_button.x()
                delta_y = event.y() - self._last_pos_middle_button.y()
                self.horizontalScrollBar().setValue(
                    self.horizontalScrollBar().value() - delta_x)
                self.verticalScrollBar().setValue(
                    self.verticalScrollBar().value() - delta_y)
                self._last_pos_middle_button = event.pos()
            elif self._last_button_press == Qt.RightButton:
                self.anno_paint(event.x(),
                                event.y(),
                                erase=True,
                                new_step=False)

    def mouseReleaseEvent(self, event: QtGui.QMouseEvent):
        self._last_button_press = Qt.NoButton

        if self.brush_stats['type'] == BRUSH_TYPE_NO_BRUSH:
            if event.button() == Qt.MiddleButton:
                self.setCursor(Qt.ArrowCursor)
        if self.brush_stats['type'] in [
                BRUSH_TYPE_CIRCLE_BRUSH, BRUSH_TYPE_RECT_BRUSH
        ]:
            if event.button() == Qt.LeftButton:
                pass
            elif event.button() == Qt.RightButton:
                pass
        else:
            super(ASCGraphicsView, self).mouseReleaseEvent(event)

    def wheelEvent(self, event: QtGui.QWheelEvent):
        # super(ASCGraphicsView, self).wheelEvent(event)
        if self.objectName() == 'aGraphicsView':
            if event.angleDelta().y() > 0:
                self.move_focus_point_signal.emit(0, 0, -1)
            elif event.angleDelta().y() < 0:
                self.move_focus_point_signal.emit(0, 0, 1)
        if self.objectName() == 'sGraphicsView':
            if event.angleDelta().y() > 0:
                self.move_focus_point_signal.emit(-1, 0, 0)
            elif event.angleDelta().y() < 0:
                self.move_focus_point_signal.emit(1, 0, 0)
        if self.objectName() == 'cGraphicsView':
            if event.angleDelta().y() > 0:
                self.move_focus_point_signal.emit(0, -1, 0)
            elif event.angleDelta().y() < 0:
                self.move_focus_point_signal.emit(0, 1, 0)

    def leaveEvent(self, event: QtCore.QEvent):
        self._last_button_press = Qt.NoButton
        if self.brush_stats['type'] == BRUSH_TYPE_NO_BRUSH:
            super(ASCGraphicsView, self).leaveEvent(event)
        else:
            self.update_brush_preview(0, 0, out_of_sight=True)
Пример #12
0
class TransitionGraphicsItem(QGraphicsObject):
    # constant values
    SQUARE_SIDE = 10
    ARROW_SIZE = 12
    PEN_NORMAL_WIDTH = 1
    PEN_FOCUS_WIDTH = 3

    posChanged = pyqtSignal('QGraphicsItem')

    def __init__(self, data):
        super(QGraphicsObject, self).__init__()
        self.transitionData = data

        self.originLine = None
        self.destinationLine = None
        self.arrow = None
        self.textGraphics = None
        self.middleHandle = None

        self.graphicsOrigin = self.transitionData.origin.getGraphicsItem()
        self.graphicsDestination = self.transitionData.destination.getGraphicsItem(
        )

        # connect position changed event
        self.graphicsOrigin.posChanged.connect(self.statePosChanged)
        self.graphicsDestination.posChanged.connect(self.statePosChanged)

        self.midPointX = (self.graphicsDestination.scenePos().x() +
                          self.graphicsOrigin.scenePos().x()) / 2.0
        self.midPointY = (self.graphicsDestination.scenePos().y() +
                          self.graphicsOrigin.scenePos().y()) / 2.0

        self.createOriginLine()
        self.createDestinationLine()

        self.createArrow()
        self.createMiddleHandle()
        self.createIdTextBox()

    def statePosChanged(self, state):
        if self.graphicsOrigin == state:
            self.createOriginLine()
        elif self.graphicsDestination == state:
            self.createDestinationLine()
            self.createArrow()

    def createOriginLine(self):
        if self.originLine == None:
            self.originLine = QGraphicsLineItem(
                self.midPointX, self.midPointY,
                self.graphicsOrigin.scenePos().x(),
                self.graphicsOrigin.scenePos().y(), self)
        else:
            self.originLine.setLine(
                QLineF(self.midPointX, self.midPointY,
                       self.graphicsOrigin.scenePos().x(),
                       self.graphicsOrigin.scenePos().y()))
        myLine = self.originLine.line()
        myLine.setLength(myLine.length() - StateGraphicsItem.NODE_WIDTH / 2)
        self.originLine.setLine(myLine)

    def createDestinationLine(self):
        if self.destinationLine == None:
            self.destinationLine = QGraphicsLineItem(
                self.midPointX, self.midPointY,
                self.graphicsDestination.scenePos().x(),
                self.graphicsDestination.scenePos().y(), self)
        else:
            self.destinationLine.setLine(
                QLineF(self.midPointX, self.midPointY,
                       self.graphicsDestination.scenePos().x(),
                       self.graphicsDestination.scenePos().y()))

        myLine = self.destinationLine.line()
        myLine.setLength(myLine.length() - StateGraphicsItem.NODE_WIDTH / 2)
        self.destinationLine.setLine(myLine)

    def createArrow(self):
        # add an arrow to destination line
        myLine = self.destinationLine.line()
        myLine.setLength(myLine.length() - TransitionGraphicsItem.ARROW_SIZE)
        rotatePoint = myLine.p2() - self.destinationLine.line().p2()

        rightPointX = rotatePoint.x() * math.cos(
            math.pi / 6) - rotatePoint.y() * math.sin(math.pi / 6)
        rightPointY = rotatePoint.x() * math.sin(
            math.pi / 6) + rotatePoint.y() * math.cos(math.pi / 6)
        rightPoint = QPointF(rightPointX + self.destinationLine.line().x2(),
                             rightPointY + self.destinationLine.line().y2())

        leftPointX = rotatePoint.x() * math.cos(
            -math.pi / 6) - rotatePoint.y() * math.sin(-math.pi / 6)
        leftPointY = rotatePoint.x() * math.sin(
            -math.pi / 6) + rotatePoint.y() * math.cos(-math.pi / 6)
        leftPoint = QPointF(leftPointX + self.destinationLine.line().x2(),
                            leftPointY + self.destinationLine.line().y2())

        polygon = QPolygonF()
        polygon << rightPoint << leftPoint << self.destinationLine.line().p2(
        ) << rightPoint

        if self.arrow == None:
            self.arrow = QGraphicsPolygonItem(polygon, self)
        else:
            self.arrow.setPolygon(polygon)

        brush = QBrush(Qt.SolidPattern)
        brush.setColor(Qt.black)
        self.arrow.setBrush(brush)

    def createMiddleHandle(self):
        # create middle handle
        if self.middleHandle == None:
            self.middleHandle = RectHandleGraphicsItem(
                TransitionGraphicsItem.SQUARE_SIDE, self)
            self.middleHandle.setFlag(QGraphicsItem.ItemIsMovable)

        self.middleHandle.setPos(self.midPointX, self.midPointY)

    def createIdTextBox(self):
        if self.textGraphics == None:
            self.textGraphics = IdTextBoxGraphicsItem(self.transitionData.name,
                                                      self)
            self.textGraphics.textChanged.connect(self.nameChanged)
        else:
            self.textGraphics.setPlainText(self.transitionData.name)
        textWidth = self.textGraphics.boundingRect().width()
        self.textGraphics.setPos(
            self.midPointX - textWidth / 2,
            self.midPointY + TransitionGraphicsItem.SQUARE_SIDE -
            (TransitionGraphicsItem.SQUARE_SIDE / 2) + 5)

    def updateMiddlePoints(self, newPosition):
        self.midPointX = newPosition.x()
        self.midPointY = newPosition.y()
        self.createOriginLine()
        self.createDestinationLine()
        self.createArrow()
        self.createIdTextBox()
        self.posChanged.emit(self)

    def nameChanged(self, name):
        self.transitionData.name = name
        self.createIdTextBox()

    def boundingRect(self):
        if self.middleHandle != None:
            return self.middleHandle.boundingRect()
        else:
            return None

    def disableInteraction(self):
        if self.middleHandle is not None:
            self.middleHandle.setFlag(QGraphicsItem.ItemIsMovable, False)
            self.middleHandle.disableInteraction()
Пример #13
0
 def on_qAction15_triggered(self):
     item = QGraphicsPolygonItem()
     points = [QPointF(0, -40), QPointF(60, 40), QPointF(-60, 40)]
     item.setPolygon(QPolygonF(points))
     item.setBrush(QBrush(Qt.magenta))
     self.__setItemProperties(item, "三角形")