Exemplo n.º 1
0
class MyArrow(QGraphicsLineItem):
    def __init__(self, scene, Source, Dest):
        super(MyArrow, self).__init__()
        #设置起点x,y
        Source_x = Source[0]
        Source_y = Source[1]
        #设置终点x,y
        Dest_x = Dest[0]
        Dest_y = Dest[1]
        #绘制连线
        self.source = QPointF(Source_x, Source_y)
        self.dest = QPointF(Dest_x, Dest_y)
        self.line = QLineF(self.source, self.dest)
        self.line.setLength(self.line.length() - 20)
        scene.addItem(self)

    def prepareGeometryChange(self):
        self.update()

    def paint(self, QPainter, QStyleOptionGraphicsItem, QWidget_widget=None):

        # setPen
        pen = QPen()
        pen.setWidth(2)
        pen.setJoinStyle(Qt.MiterJoin)
        QPainter.setPen(pen)

        # setBrush
        brush = QBrush()
        brush.setColor(Qt.black)
        brush.setStyle(Qt.SolidPattern)
        QPainter.setBrush(brush)

        #绘制终点箭头
        v = self.line.unitVector()
        v.setLength(10)
        v.translate(QPointF(self.line.dx(), self.line.dy()))

        n = v.normalVector()
        n.setLength(n.length() * 0.5)
        n2 = n.normalVector().normalVector()

        p1 = v.p2()
        p2 = n.p2()
        p3 = n2.p2()

        QPainter.drawLine(self.line)
        QPainter.drawPolygon(p1, p2, p3)
Exemplo n.º 2
0
    def draw_arrow(self, QPainter, point_1: QPointF,
                   point_2: QPointF) -> 'QPolygonF':
        """
        绘制箭头。
        :param QPainter:
        :param point_1:
        :param point_2:
        :return:
        """

        line = QLineF(point_1, point_2)
        v = line.unitVector()

        v.setLength(20)  # 改变单位向量的大小,实际就是改变箭头长度
        v.translate(QPointF(int(line.dx() / 2), int(line.dy() / 2)))

        n = v.normalVector()  # 法向量
        n.setLength(n.length() * 0.2)  # 这里设定箭头的宽度
        n2 = n.normalVector().normalVector()  # 两次法向量运算以后,就得到一个反向的法向量
        p1 = v.p2()
        p2 = n.p2()
        p3 = n2.p2()
        QPainter.drawPolygon(p1, p2, p3)
        return QPolygonF([p1, p2, p3, p1])
Exemplo n.º 3
0
class ArrowLine(object):
    def __init__(self, pos1, pos2, from_node=None, end_node=None):
        self.__source = QPointF(pos1[0], pos1[1])
        self.__dest = QPointF(pos2[0], pos2[1])
        self.__line = QLineF(self.__source, self.__dest)

        self.__arrowLen = 10
        # self.__line.setLength(self.__line.length() - self.__arrowLen)
        self.__penWidth = 2
        self.__pen = QPen()
        self.__brush = QBrush()
        self.__color = QColor(255, 0, 0)
        self.__arrowRatio = 1.0
        self.__isSolid = True
        self.__from_node = from_node
        self.__end_node = end_node

    def get_from_node(self):
        return self.__from_node

    def get_end_node(self):
        return self.__end_node

    def set_arrow_len(self, length):
        self.__arrowLen = length

    def get_arrow_len(self):
        return self.__arrowLen

    def set_pen_width(self, width):
        self.__penWidth = width

    def get_pen_width(self):
        return self.__penWidth

    def set_arrow_solid(self, flag):
        self.__isSolid = flag

    def is_arrow_solid(self):
        return self.__isSolid

    def set_color(self, color):
        self.__color = color

    def get_color(self):
        return self.__color

    def get_line(self):
        return self.__line

    def paint(self, QPainter):
        # setPen
        self.__pen.setWidth(self.__penWidth)
        self.__pen.setColor(self.__color)
        QPainter.setPen(self.__pen)

        # setBrush
        if self.__isSolid:
            self.__brush.setColor(self.__color)
            self.__brush.setStyle(Qt.SolidPattern)
            QPainter.setBrush(self.__brush)

        v = self.__line.unitVector()
        v.setLength(self.__arrowLen)
        v.translate(
            QPointF(self.__line.dx() * self.__arrowRatio,
                    self.__line.dy() * self.__arrowRatio))

        # width of arrow
        n = v.normalVector()
        n.setLength(n.length() * 0.5)
        n2 = n.normalVector().normalVector()

        QPainter.drawLine(self.__line)
        QPainter.drawPolygon(v.p2(), n.p2(), n2.p2())
Exemplo n.º 4
0
class GraphicEdge(QGraphicsPathItem):

    def __init__(self, edge_wrap, directed, parent=None):
        super().__init__(parent)
        self.edge_wrap = edge_wrap
        self.width = 3.0
        self.pos_src = [0, 0]
        self.pos_dst = [0, 0]
        # 是否有向
        self.directed = directed
        self.flag = 0
        self.capacity = self.edge_wrap.capacity

        self.setAcceptHoverEvents(True)
        # 普通画图时的pen样式
        self._n_pen = QPen(QColor("#000"))
        self._n_pen.setWidthF(self.width)
        # 画图时的pen样式
        self._pen = self._n_pen
        # 悬浮时的pen样式
        self._hover_pen = QPen(Qt.green)
        self._hover_pen.setWidthF(self.width)
        # 拖拽时的样式
        self._pen_dragging = QPen(QColor("#000"))
        self._pen_dragging.setStyle(Qt.DashDotLine)
        self._pen_dragging.setWidthF(self.width)

        self._mark_brush = QBrush()
        self._mark_brush.setColor(Qt.green)
        self._mark_brush.setStyle(Qt.SolidPattern)

        self._normal_brush = QBrush()
        self._normal_brush.setColor(Qt.black)
        self._normal_brush.setStyle(Qt.SolidPattern)

        self.brush = self._normal_brush

        self.setFlag(QGraphicsItem.ItemIsSelectable)
        self.setZValue(-1)

    def set_src(self, x, y):
        self.pos_src = [x, y]

    def set_dst(self, x, y):
        self.pos_dst = [x, y]

    def calc_path(self):
        path = QPainterPath(QPointF(self.pos_src[0], self.pos_src[1]))  # 起点
        path.lineTo(QPointF(self.pos_dst[0], self.pos_dst[1]))  # 终点
        if self.directed:
            # 画箭头
            self.line = QLineF(QPointF(self.pos_src[0], self.pos_src[1]), QPointF(self.pos_dst[0], self.pos_dst[1]))
            if self.flag == 0:
                self.line.setLength(self.line.length() - 20)
            else:
                self.line.setLength(self.line.length() - self.edge_wrap.end_item.r)
            v = self.line.unitVector()
            v.setLength(20)
            v.translate(QPointF(self.line.dx(), self.line.dy()))

            n = v.normalVector()
            n.setLength(n.length() * 0.5)
            n2 = n.normalVector().normalVector()

            p1 = v.p2()
            p2 = n.p2()
            p3 = n2.p2()
            # 方法2
            arrow = QPolygonF([p1, p2, p3, p1])
            path.addPolygon(arrow)
        # path = QPainterPath(QPointF(self.pos_src[0], self.pos_src[1]))
        # path.lineTo(self.pos_dst[0], self.pos_dst[1])
        return path

    def boundingRect(self):
        return self.shape().boundingRect()

    def hoverEnterEvent(self, event: 'QGraphicsSceneHoverEvent'):
        self.brush = self._mark_brush
        self._pen = self._hover_pen
        self.update()

    def hoverLeaveEvent(self, event: 'QGraphicsSceneHoverEvent'):
        self.brush = self._normal_brush
        self._pen = self._n_pen
        self.update()

    def shape(self):
        # 设置宽度 这里用了100 很大
        qps = QPainterPathStroker()
        qps.setWidth(100)
        return qps.createStroke(self.calc_path())

    def paint(self, painter, graphics_item, widget=None):

        if self.edge_wrap.end_item is None:
            self.ensureVisible()
            self.setPath(self.calc_path())
            path = self.path()

            painter.setPen(self._pen_dragging)
            painter.setBrush(self.brush)
            painter.drawPath(path)
        else:
            # 这画的才是连接后的线
            self.flag = 1
            self.setPath(self.calc_path())  # 设置路径
            path = self.path()
            painter.setPen(self._pen)
            painter.setBrush(self.brush)
            painter.drawPath(path)
            self.flag = 0
            painter.setFont(QFont("Times New Roman", 16))
            painter.setPen(Qt.red)
            x = int((self.pos_src[0] + self.pos_dst[0]) / 2 - 17)
            y = int((self.pos_src[1] + self.pos_dst[1]) / 2 - 7)
            painter.drawText(x, y, "({}) {}".format(self.edge_wrap.id, self.capacity))
Exemplo n.º 5
0
class EdgeItem(QGraphicsLineItem):
    def __init__(self,
                 boxName,
                 fromLocation,
                 toLocation,
                 guard,
                 reset,
                 scene,
                 parentForm,
                 style=Qt.SolidLine,
                 rect=None,
                 matrix=QTransform()):
        super(EdgeItem, self).__init__()

        self.setFlags(QGraphicsItem.ItemIsSelectable
                      | QGraphicsItem.ItemIsMovable
                      | QGraphicsItem.ItemIsFocusable)
        self.style = style
        self.boxName = boxName
        self.guard = guard
        self.reset = reset
        self._fromLocation = None
        self._toLocation = None
        if fromLocation == None:
            x1 = 10
            y1 = 10
        else:
            x1 = fromLocation.rect.right()
            y1 = fromLocation.rect.top() + fromLocation.rect.height() * 0.3
        if toLocation == None:
            x2 = 100
            y2 = 100
        else:
            x2 = toLocation.rect.left()
            y2 = toLocation.rect.top() + fromLocation.rect.height() * 0.3
        self.parentForm = parentForm
        self.source = QPointF(x1, y1)
        self.dest = QPointF(x2, y2)
        self.fromLocation = fromLocation
        self.toLocation = toLocation
        self.direction = "a"
        self.myColor = Qt.black
        self.setPen(
            QPen(self.myColor, 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        self.line = QLineF(self.source, self.dest)
        self.line.setLength(self.line.length() - 5)
        self.resetLine()
        self.scene = scene
        scene.clearSelection()
        scene.addItem(self)
        self.setSelected(True)
        self.setFocus()
        global Dirty
        Dirty = True

    def drawLine2Self(self):
        haveEdges = [
            strDirection for strDirection in self.fromLocation.edges.values()
        ]
        self.arcx1 = self.fromLocation.x() + self.fromLocation.rect.x(
        ) - 40  #-30
        self.arcy1 = self.fromLocation.y() + self.fromLocation.rect.y(
        )  # -50#+self.fromLocation.rect.height*0.3
        self.minAngle = 90
        x1 = self.arcx1 + 33
        y1 = self.arcy1 + 80
        x2 = self.arcx1 + 40
        y2 = self.arcy1 + 80
        self.arcTextx = self.arcx1
        self.arcTexty = self.arcy1 + 40
        self.spanAngle = 180
        if "top" not in haveEdges and self.fromLocation.isNameAbove == False:
            self.arcx1 = self.fromLocation.x() + self.fromLocation.rect.x(
            ) + 10
            self.arcy1 = self.fromLocation.y() + self.fromLocation.rect.y(
            ) - 40
            x1 = self.arcx1 + 80
            y1 = self.arcy1 + 40 - 7
            x2 = self.arcx1 + 80
            y2 = self.arcy1 + 40
            self.minAngle = 0
            self.arcTextx = self.arcx1 + 40
            self.arcTexty = self.arcy1
        elif "left" not in haveEdges:
            self.arcx1 = self.fromLocation.x() + self.fromLocation.rect.x(
            ) - 40  #-30
            self.arcy1 = self.fromLocation.y() + self.fromLocation.rect.y(
            ) + 10  # -50#+self.fromLocation.rect.height*0.3
            self.minAngle = 90
            x1 = self.arcx1 + 33
            y1 = self.arcy1 + 80
            x2 = self.arcx1 + 40
            y2 = self.arcy1 + 80
            self.arcTextx = self.arcx1
            self.arcTexty = self.arcy1 + 40
        elif "bottom" not in haveEdges and self.fromLocation.isNameAbove:
            self.arcx1 = self.fromLocation.x() + self.fromLocation.rect.x(
            ) + 10
            self.arcy1 = self.fromLocation.y() + self.fromLocation.rect.y(
            ) + self.fromLocation.rect.height() - 40
            self.minAngle = 180
            x1 = self.arcx1 + 80
            y1 = self.arcy1 + 7 + 40
            x2 = self.arcx1 + 80
            y2 = self.arcy1 + 40
            self.arcTextx = self.arcx1 + 40
            self.arcTexty = self.arcy1 + 80
        elif "right" not in haveEdges:
            self.arcx1 = self.fromLocation.x() + self.fromLocation.rect.x(
            ) + self.fromLocation.rect.width() - 40  #-30
            self.arcy1 = self.fromLocation.y() + self.fromLocation.rect.y(
            ) + 10  # -50#+self.fromLocation.rect.height*0.3
            self.minAngle = 270
            x1 = self.arcx1 + 7 + 25 + adjustX1
            y1 = self.arcy1 + 80
            x2 = self.arcx1 + 25 + adjustX1
            y2 = self.arcy1 + 80
            self.arcTextx = self.arcx1 + 80
            self.arcTexty = self.arcy1 + 40
        self.source = QPointF(x1, y1)
        self.dest = QPointF(x2, y2)
        self.line = QLineF(self.source, self.dest)
        self.line.setLength(self.line.length() - 5)
#if 'time' not in listOfStrings :
#  print("Yes, 'time' NOT found in List : " , listOfStrings)

    def getQPixmap4Guard(self):
        guardFig = Figure(figsize=(5, 0.4))
        canvas = FigureCanvas(guardFig)
        strData = self.guard
        try:
            guardFig.text(0.1, 0.3, strData, family="Consolas", fontsize=10)
        except:
            pass
        canvas.draw()
        size = canvas.size()
        width, height = size.width(), size.height()
        im = QImage(canvas.buffer_rgba(), width, height, QImage.Format_ARGB32)
        return QPixmap(im)

    def getQPixmap4Reset(self):
        guardFig = Figure(figsize=(5, 0.4))
        canvas = FigureCanvas(guardFig)
        strData = self.reset
        try:
            guardFig.text(0.1, 0.3, strData, family="Consolas", fontsize=10)
        except:
            pass
        canvas.draw()
        size = canvas.size()
        width, height = size.width(), size.height()
        im = QImage(canvas.buffer_rgba(), width, height, QImage.Format_ARGB32)
        return QPixmap(im)

    def resetLine(self):
        self.direction = ""
        if self.fromLocation == None and self.toLocation == None:
            return

        if self.fromLocation == None:
            #self.toLocation.edges[self.boxName]="left"
            x2 = self.toLocation.x() + self.toLocation.rect.x()
            y2 = self.toLocation.y() + self.toLocation.rect.x(
            ) + self.toLocation.rect.height() * 0.3
            x1 = x2 - 30
            y1 = y2
        elif self.toLocation == None:
            #self.fromLocation.edges[self.boxName]="right"
            x1 = self.fromLocation.x() + self.fromLocation.rect.x(
            ) + self.fromLocation.rect.width()
            y1 = self.fromLocation.y() + self.fromLocation.rect.y(
            ) + self.fromLocation.rect.height() * 0.3
            x2 = x1 + 30
            y2 = y1
        else:
            adjustX1 = self.fromLocation.x() + self.fromLocation.rect.x()
            adjustX2 = self.toLocation.x() + self.toLocation.rect.x()
            adjustY1 = self.fromLocation.y() + self.fromLocation.rect.y()
            adjustY2 = self.toLocation.y() + self.toLocation.rect.y()
            if self.fromLocation.boxName == self.toLocation.boxName:
                self.drawLine2Self()
                self.fromLocation.edgeToSelf = self.boxName
                return
            x_diff = self.toLocation.x() - self.fromLocation.x()
            y_diff = self.toLocation.y() - self.fromLocation.y()
            x_diff_standand = (self.fromLocation.rect.width() +
                               self.toLocation.rect.width()) / 2
            y_diff_standand = (self.fromLocation.rect.height() +
                               self.toLocation.rect.height()) / 2
            if ((abs(y_diff) < y_diff_standand)):
                if x_diff > 0:

                    self.direction = "x>"

                    self.fromLocation.edges[self.boxName] = "right"
                    self.toLocation.edges[self.boxName] = "left"
                    x1 = self.fromLocation.rect.width() + adjustX1
                    y1 = self.fromLocation.rect.height() * 0.4 + adjustY1
                    x2 = adjustX2
                    y2 = self.toLocation.rect.height() * 0.4 + adjustY2
                else:
                    self.direction = "x<"
                    self.fromLocation.edges[self.boxName] = "left"
                    self.toLocation.edges[self.boxName] = "right"
                    x1 = adjustX1
                    y1 = self.fromLocation.rect.height() * 0.6 + adjustY1
                    x2 = self.toLocation.rect.width() + adjustX2
                    y2 = self.toLocation.rect.height() * 0.6 + adjustY2
            elif ((abs(x_diff) < x_diff_standand)):
                if (y_diff > 0):
                    self.direction = "y>"

                    self.fromLocation.edges[self.boxName] = "bottom"
                    self.toLocation.edges[self.boxName] = "top"
                    x1 = self.fromLocation.rect.width() * 0.4 + adjustX1
                    y1 = self.fromLocation.rect.height() + adjustY1
                    x2 = self.toLocation.rect.width() * 0.4 + adjustX2
                    y2 = adjustY2
                else:
                    self.direction = "y<"
                    self.fromLocation.edges[self.boxName] = "top"
                    self.toLocation.edges[self.boxName] = "bottom"
                    x1 = self.fromLocation.rect.width() * 0.6 + adjustX1
                    y1 = adjustY1
                    x2 = self.toLocation.rect.width() * 0.6 + adjustX2
                    y2 = self.toLocation.rect.height() + adjustY2
            else:
                if (x_diff > 0) and (y_diff > 0):
                    self.direction = "xy>"
                    self.fromLocation.edges[self.boxName] = "right"
                    self.toLocation.edges[self.boxName] = "top"
                    x1 = self.fromLocation.rect.width() + adjustX1
                    y1 = self.fromLocation.rect.height() * 0.8 + adjustY1
                    x2 = self.toLocation.rect.width() * 0.2 + adjustX2
                    y2 = adjustY2
                elif ((x_diff < 0) and (y_diff < 0)):
                    self.direction = "xy<"
                    self.fromLocation.edges[self.boxName] = "left"
                    self.toLocation.edges[self.boxName] = "bottom"
                    x1 = adjustX1
                    y1 = self.fromLocation.rect.height() * 0.2 + adjustY1
                    x2 = self.toLocation.rect.width() * 0.8 + adjustX2
                    y2 = self.toLocation.rect.height() + adjustY2
                elif (x_diff > 0) and (y_diff < 0):
                    self.direction = "x>y<"
                    self.fromLocation.edges[self.boxName] = "top"
                    self.toLocation.edges[self.boxName] = "left"
                    x1 = self.fromLocation.rect.width() * 0.8 + adjustX1
                    y1 = adjustY1
                    x2 = adjustX2
                    y2 = self.toLocation.rect.height() * 0.8 + adjustY2
                else:
                    self.direction = "x<y>"
                    self.fromLocation.edges[self.boxName] = "bottom"
                    self.toLocation.edges[self.boxName] = "right"
                    x1 = self.fromLocation.rect.width() * 0.2 + adjustX1
                    y1 = adjustY1 + self.fromLocation.rect.height()
                    x2 = adjustX2 + self.toLocation.rect.width()
                    y2 = self.toLocation.rect.height() * 0.2 + adjustY2
        self.direction = self.direction + " fLX:" + str(
            self.fromLocation.x()) + ",fLrx" + str(
                self.fromLocation.rect.x()) + ",fLrw" + str(
                    self.fromLocation.rect.width()) + ",Lx" + str(x1)
        self.source = QPointF(x1, y1)
        self.dest = QPointF(x2, y2)
        self.line = QLineF(self.source, self.dest)
        self.line.setLength(self.line.length() - 5)

    @property
    def boxName(self):
        return self._boxName

    @boxName.setter
    def boxName(self, value):
        if not isinstance(value, str):
            raise ValueError('EdgeName must be an string!')
        self._boxName = value

    @property
    def guard(self):
        return self._guard

    @guard.setter
    def guard(self, value):
        if not isinstance(value, str):
            raise ValueError('EdgeName must be an string!')
        self._guard = value

    @property
    def reset(self):
        return self._reset

    @reset.setter
    def reset(self, value):
        if not isinstance(value, str):
            raise ValueError('EdgeName must be an string!')
        self._reset = value

    def toSaveJson(self):
        data = {
            "type": "Edge",
            "boxName": self.boxName,
            "strFromLocation": self.fromLocation.boxName,
            "strToLocation": self.toLocation.boxName,
            "guard": self.guard,
            "reset": self.reset,
            "style": self.style,
            "rotation": self.rotation()
        }

        return data

    @property
    def fromLocation(self):
        return self._fromLocation

    @fromLocation.setter
    def fromLocation(self, value):
        if value != None:
            if not isinstance(value, LocationItem):
                raise ValueError('LocationName must be a  LocationItem!')
            self._fromLocation = value
            self.resetLine()

    @property
    def toLocation(self):
        return self._toLocation

    @toLocation.setter
    def toLocation(self, value):
        if value != None:
            if not isinstance(value, LocationItem):
                raise ValueError('LocationName must be a LocationItem!')
            self._toLocation = value
            self.resetLine()

    def parentWidget(self):
        return self.scene.views()[0]

    def itemChange(self, change, variant):
        if change != QGraphicsItem.ItemSelectedChange:
            global Dirty
            Dirty = True
        return QGraphicsLineItem.itemChange(self, change, variant)

    def mouseDoubleClickEvent(self, event):
        dialog = edgeItemDlg(self, self.parentWidget(), self.parentWidget(),
                             self.scene, self.parentForm)
        dialog.exec_()

    def paint(self, QPainter, QStyleOptionGraphicsItem, QWidget_widget=None):
        # setPen
        pen = QPen()
        pen.setWidth(1)
        pen.setJoinStyle(Qt.MiterJoin)  #让箭头变尖
        QPainter.setPen(pen)

        # draw line
        QPainter.drawLine(self.line)
        ptextx = (self.line.x1() + self.line.x2()) / 2
        ptexty = (self.line.y1() + self.line.y2()) / 2
        ptexty -= 5
        ptextx -= len(self.boxName) * 3

        #QPainter.drawText(QPointF(ptextx, ptexty+20), self.direction)
        # setBrush
        brush = QBrush()
        brush.setColor(Qt.black)
        brush.setStyle(Qt.SolidPattern)
        QPainter.setBrush(brush)

        v = self.line.unitVector()
        v.setLength(5)
        v.translate(QPointF(self.line.dx(), self.line.dy()))

        n = v.normalVector()
        n.setLength(n.length() * 0.5)
        n2 = n.normalVector().normalVector()

        p1 = v.p2()
        p2 = n.p2()
        p3 = n2.p2()

        # 方法1
        QPainter.drawLine(self.line)
        QPainter.drawPolygon(p1, p2, p3)

        if self.fromLocation is not None and self.toLocation is not None:
            if self.fromLocation.boxName == self.toLocation.boxName:
                QPainter.drawArc(self.arcx1, self.arcy1, 80, 80,
                                 self.minAngle * 16, self.spanAngle * 16)
                ptextx = self.arcTextx
                ptexty = self.arcTexty
                #QPainter.drawArc(self.arcx1, self.arcy1+100, 50, 50, 270*16, 89*16)

                #QPainter.drawArc(self.arcx1, self.arcy1+200, 50, 50, 0*16, 89*16)

                #QPainter.drawArc(self.arcx1, self.arcy1+300, 50, 50, 270*16, 180*16)

                #QPainter.drawArc(self.arcx1, self.arcy1+400, 50, 50, 270*16, 270*16)
                #QPainter.drawArc(self.arcx1, self.arcy1+500, 50, 50, 180*16, 89*16)

        QPainter.drawText(QPointF(ptextx, ptexty), self.boxName)

        #QPainter.drawRect(self.arcx1, self.arcy1, 50, 50)
        self.scene.update()
Exemplo n.º 6
0
class LineItem(QGraphicsLineItem):
    def __init__(self,
                 boxName,
                 fromBox,
                 toBox,
                 position,
                 scene,
                 parentForm,
                 style=Qt.SolidLine,
                 rect=None,
                 matrix=QTransform()):
        super(LineItem, self).__init__()

        self.setFlags(QGraphicsItem.ItemIsSelectable
                      | QGraphicsItem.ItemIsMovable
                      | QGraphicsItem.ItemIsFocusable)
        self.style = style
        self.boxName = boxName
        self._fromBox = None
        self._toBox = None
        if fromBox == None:
            x1 = 10
            y1 = 10
        else:
            x1 = fromBox.boundingRect().right()
            y1 = fromBox.boundingRect().top(
            ) + fromBox.boundingRect().height() * 0.3
        if toBox == None:
            x2 = 100
            y2 = 100
        else:
            x2 = toBox.boundingRect().left()
            y2 = toBox.boundingRect().top(
            ) + fromBox.boundingRect().height() * 0.3
        self.parentForm = parentForm
        self.source = QPointF(x1, y1)
        self.dest = QPointF(x2, y2)
        self.fromBox = fromBox
        self.toBox = toBox
        self.direction = "a"
        self.myColor = Qt.black
        self.setPen(
            QPen(self.myColor, 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        self.line = QLineF(self.source, self.dest)
        self.line.setLength(self.line.length() - 5)
        self.resetLine()
        self.scene = scene
        scene.clearSelection()
        scene.addItem(self)
        self.setSelected(True)
        self.setFocus()
        global Dirty
        Dirty = True

    def resetLine(self):
        if self.fromBox == None and self.toBox == None:
            return
        if self.fromBox == None:
            x2 = self.toBox.x()
            y2 = self.toBox.y() + self.toBox.boundingRect().height() * 0.3
            x1 = x2 - 30
            y1 = y2
        elif self.toBox == None:
            x1 = self.fromBox.x() + self.fromBox.boundingRect().width()
            y1 = self.fromBox.y() + self.fromBox.boundingRect().height() * 0.3
            x2 = x1 + 30
            y2 = y1
        else:
            x_diff = self.toBox.x() - self.fromBox.x()
            y_diff = self.toBox.y() - self.fromBox.y()
            x_diff_standand = (self.fromBox.boundingRect().width() +
                               self.toBox.boundingRect().width()) / 2
            y_diff_standand = (self.fromBox.boundingRect().height() +
                               self.toBox.boundingRect().height()) / 2
            if ((abs(y_diff) < y_diff_standand)):
                if x_diff > 0:

                    self.direction = "x>"
                    x1 = self.fromBox.x() + self.fromBox.boundingRect().width()
                    y1 = self.fromBox.y(
                    ) + self.fromBox.boundingRect().height() * 0.3
                    x2 = self.toBox.x()
                    y2 = self.toBox.y(
                    ) + self.toBox.boundingRect().height() * 0.3
                else:
                    self.direction = "x<"
                    x1 = self.fromBox.x()
                    y1 = self.fromBox.y(
                    ) + self.fromBox.boundingRect().height() * 0.67
                    x2 = self.toBox.x() + self.toBox.boundingRect().width()
                    y2 = self.toBox.y(
                    ) + self.toBox.boundingRect().height() * 0.67
            elif ((abs(x_diff) < x_diff_standand)):
                if (y_diff > 0):
                    self.direction = "y>"
                    x1 = self.fromBox.x(
                    ) + self.fromBox.boundingRect().width() * 0.3
                    y1 = self.fromBox.y() + self.fromBox.boundingRect().height(
                    )
                    x2 = self.toBox.x(
                    ) + self.toBox.boundingRect().width() * 0.3
                    y2 = self.toBox.y()
                else:
                    self.direction = "y<"
                    x1 = self.fromBox.x(
                    ) + self.fromBox.boundingRect().width() * 0.67
                    y1 = self.fromBox.y()
                    x2 = self.toBox.x(
                    ) + self.toBox.boundingRect().width() * 0.67
                    y2 = self.toBox.y() + self.toBox.boundingRect().height()
            else:
                if (x_diff > 0) and (y_diff > 0):
                    self.direction = "xy>"
                    x1 = self.fromBox.x() + self.fromBox.boundingRect().width()
                    y1 = self.fromBox.y(
                    ) + self.fromBox.boundingRect().height() * 0.87
                    x2 = self.toBox.x(
                    ) + self.toBox.boundingRect().width() * 0.13
                    y2 = self.toBox.y()
                elif ((x_diff < 0) and (y_diff < 0)):
                    self.direction = "xy<"
                    x1 = self.fromBox.x()
                    y1 = self.fromBox.y(
                    ) + self.fromBox.boundingRect().height() * 0.13
                    x2 = self.toBox.x(
                    ) + self.toBox.boundingRect().width() * 0.87
                    y2 = self.toBox.y() + self.toBox.boundingRect().height()
                elif (x_diff > 0) and (y_diff < 0):
                    self.direction = "x>y<"
                    x1 = self.fromBox.x(
                    ) + self.fromBox.boundingRect().width() * 0.87
                    y1 = self.fromBox.y()
                    x2 = self.toBox.x()
                    y2 = self.toBox.y(
                    ) + self.toBox.boundingRect().height() * 0.87
                else:
                    self.direction = "x<y>"
                    x1 = self.fromBox.x(
                    ) + self.fromBox.boundingRect().width() * 0.13
                    y1 = self.fromBox.y() + self.fromBox.boundingRect().height(
                    )
                    x2 = self.toBox.x() + self.toBox.boundingRect().width()
                    y2 = self.toBox.y(
                    ) + self.toBox.boundingRect().height() * 0.13
        self.source = QPointF(x1, y1)
        self.dest = QPointF(x2, y2)
        self.line = QLineF(self.source, self.dest)
        self.line.setLength(self.line.length() - 5)

    @property
    def boxName(self):
        return self._boxName

    @boxName.setter
    def boxName(self, value):
        if not isinstance(value, str):
            raise ValueError('boxName must be an string!')
        self._boxName = value

    def toSaveJson(self):
        data = {
            "type": "Line",
            "boxName": self.boxName,
            "strFromBox": self.fromBox.boxName,
            "strToBox": self.toBox.boxName,
            "style": self.style,
            "rotation": self.rotation()
        }
        return data

    @property
    def fromBox(self):
        return self._fromBox

    @fromBox.setter
    def fromBox(self, value):
        if value != None:
            if not isinstance(value, QGraphicsTextItem):
                raise ValueError('boxName must be an string!')
            self._fromBox = value
            self.resetLine()

    @property
    def toBox(self):
        return self._toBox

    @toBox.setter
    def toBox(self, value):
        if value != None:
            if not isinstance(value, QGraphicsTextItem):
                raise ValueError('boxName must be an string!')
            self._toBox = value
            self.resetLine()

    def parentWidget(self):
        return self.scene().views()[0]

    def itemChange(self, change, variant):
        if change != QGraphicsItem.ItemSelectedChange:
            global Dirty
            Dirty = True
        return QGraphicsLineItem.itemChange(self, change, variant)

    def mouseDoubleClickEvent(self, event):
        dialog = LineItemDlg(self, self.parentWidget(), self.parentWidget(),
                             self.scene, self.parentForm)
        dialog.exec_()

    def paint(self, QPainter, QStyleOptionGraphicsItem, QWidget_widget=None):
        # setPen
        pen = QPen()
        pen.setWidth(1)
        pen.setJoinStyle(Qt.MiterJoin)  #让箭头变尖
        QPainter.setPen(pen)

        # draw line
        QPainter.drawLine(self.line)
        ptextx = (self.line.x1() + self.line.x2()) / 2
        ptexty = (self.line.y1() + self.line.y2()) / 2
        ptexty -= 5
        ptextx -= len(self.boxName) * 3
        QPainter.drawText(QPointF(ptextx, ptexty), self.boxName)

        #Painter.drawText(QPointF(ptextx, ptexty+20), self.direction)
        # setBrush
        brush = QBrush()
        brush.setColor(Qt.black)
        brush.setStyle(Qt.SolidPattern)
        QPainter.setBrush(brush)

        v = self.line.unitVector()
        v.setLength(5)
        v.translate(QPointF(self.line.dx(), self.line.dy()))

        n = v.normalVector()
        n.setLength(n.length() * 0.5)
        n2 = n.normalVector().normalVector()

        p1 = v.p2()
        p2 = n.p2()
        p3 = n2.p2()

        # 方法1
        QPainter.drawLine(self.line)
        QPainter.drawPolygon(p1, p2, p3)

        QPainter.drawArc(10, 10, 50, 50, 0, 180 * 16)

        v = self.line.unitVector()
        v.setLength(5)
        v.translate(QPointF(10, 60))

        n = v.normalVector()
        n.setLength(n.length() * 0.5)
        n2 = n.normalVector().normalVector()

        p1 = v.p2()
        p2 = n.p2()
        p3 = n2.p2()

        # 方法1
        #QPainter.drawLine(self.line)
        QPainter.drawPolygon(p1, p2, p3)
        self.scene.update()
Exemplo n.º 7
0
    def draw(self, qp):
        brush = QBrush()  #刷子对象
        pen = QPen()  #画笔对象
        lightgray = QColor()  #自定义颜色
        lightgray.setRgb(240, 240, 240)
        #绘制各个连接线
        for line, value in self.line_dict.items():
            if value[2] == '':  #连接线终点未指定时,绘制一条虚线,终点跟随鼠标
                pen.setStyle(Qt.DashLine)
                pen.setColor(Qt.black)
                qp.setPen(pen)
                lineF = QLineF(
                    QPoint(self.circle_dict[value[1]][1][0],
                           self.circle_dict[value[1]][1][1]),
                    QPoint(self.line_dest_pos[0], self.line_dest_pos[1]))
                e = lineF.unitVector()
                new_lineF = QLineF(
                    QPoint(
                        self.circle_dict[value[1]][1][0] +
                        int(e.dx() * self.d / 2),
                        self.circle_dict[value[1]][1][1] +
                        int(e.dy() * self.d / 2)),
                    QPoint(self.line_dest_pos[0], self.line_dest_pos[1]))
                qp.drawLine(new_lineF)
            #连接线两端的圆形是相离状态时,绘制有向箭头
            elif ((self.circle_dict[value[1]][1][0] -
                   self.circle_dict[value[2]][1][0])**2 +
                  (self.circle_dict[value[1]][1][1] -
                   self.circle_dict[value[2]][1][1])**2)**0.5 > self.d:
                lineF = QLineF(
                    QPoint(self.circle_dict[value[1]][1][0],
                           self.circle_dict[value[1]][1][1]),
                    QPoint(self.circle_dict[value[2]][1][0],
                           self.circle_dict[value[2]][1][1]))
                e = lineF.unitVector()
                new_lineF = QLineF(
                    QPoint(
                        self.circle_dict[value[1]][1][0] +
                        int(e.dx() * self.d / 2),
                        self.circle_dict[value[1]][1][1] +
                        int(e.dy() * self.d / 2)),
                    QPoint(
                        self.circle_dict[value[2]][1][0] -
                        int(e.dx() * self.d / 2),
                        self.circle_dict[value[2]][1][1] -
                        int(e.dy() * self.d / 2)))
                #如果已生成关键路径且图形是最新的,设定连接线为红色
                if line in self.critical_activity and self.isnew:
                    pen.setColor(Qt.red)
                else:  #否则连接线为黑色
                    pen.setColor(Qt.black)
                pen.setStyle(Qt.SolidLine)
                qp.setPen(pen)
                #绘制连接线
                qp.drawLine(new_lineF)

                #运用向量计算箭头三个顶点
                e.translate(new_lineF.dx() + e.dx(), new_lineF.dy() + e.dy())
                n1 = e.normalVector()
                n1.setLength(self.line_width)
                n2 = n1.normalVector().normalVector()
                #如果已生成关键路径且图形是最新的,设定箭头为红色
                if line in self.critical_activity and self.isnew:
                    brush.setColor(Qt.red)
                else:  #否则箭头为黑色
                    brush.setColor(Qt.black)
                brush.setStyle(Qt.SolidPattern)
                qp.setBrush(brush)
                #绘制箭头
                qp.drawPolygon(n1.p2(), n2.p2(), new_lineF.p2())

                #计算箭头上文字的长宽
                metrics = qp.fontMetrics()
                width = metrics.width(str(value[0]))
                height = metrics.height()
                head_pos = self.circle_dict[value[1]][1]
                tail_pos = self.circle_dict[value[2]][1]
                x = (head_pos[0] + tail_pos[0]) / 2 - width / 2
                y = (head_pos[1] + tail_pos[1]) / 2 + height / 2

                #绘制箭头上文字的底色
                brush.setColor(lightgray)
                brush.setStyle(Qt.SolidPattern)
                qp.setBrush(brush)
                pen.setColor(lightgray)
                pen.setStyle(Qt.SolidLine)
                qp.setPen(pen)
                rect = QRect()
                rect.setRect((head_pos[0] + tail_pos[0]) / 2 - width / 2,
                             (head_pos[1] + tail_pos[1]) / 2 - height / 2,
                             width, height)
                qp.drawRect(rect)

                #如果已生成关键路径且图形是最新的,设定箭头上文字为红色
                if line in self.critical_activity and self.isnew:
                    pen.setColor(Qt.red)
                else:  #否则设定文字为黑色
                    pen.setColor(Qt.black)
                pen.setStyle(Qt.SolidLine)
                qp.setPen(pen)
                #绘制箭头上文字
                qp.drawText(x, y, str(value[0]))
        #为了圆形的遮盖次序和选中次序统一,逆序绘制圆形
        circles = list(self.circle_dict.keys())
        circles.reverse()
        for circle in circles:
            value = self.circle_dict[circle]
            color = QColor()
            if self.isget and self.circle_gotton == circle:  #如果圆形被选中设定颜色为青色
                color.setRgb(100, 200, 200)
            else:  #否则设定颜色为黄色
                color.setRgb(255, 255, 150)
            brush = QBrush()
            brush.setColor(color)
            brush.setStyle(Qt.SolidPattern)
            qp.setBrush(brush)
            pen.setStyle(Qt.SolidLine)
            if circle in self.critical_affair and self.isnew:  #如果已生成关键路径且图形是最新的,设定圆形边框为红色
                pen.setColor(Qt.red)
            else:  #否则设定颜色为黑色
                pen.setColor(Qt.black)
            qp.setPen(pen)
            #绘制圆形
            qp.drawEllipse(value[1][0] - self.d / 2, value[1][1] - self.d / 2,
                           self.d, self.d)

            #获取圆形上文字的长宽
            metrics = qp.fontMetrics()
            width = metrics.width(value[0])
            height = metrics.height()
            x = value[1][0] - width / 2
            y = value[1][1] + height / 2
            #绘制圆形上文字
            qp.drawText(x, y, value[0])
        #如果结果窗口已展开但图形不是最新的
        if not self.isnew and self.parent.isdock:
            #设置主窗口状态栏
            status = QStatusBar()
            status.showMessage('运行结果已过期')
            self.parent.mw.setStatusBar(status)
            #禁用主窗口保存结果按钮
            self.parent.mw.action_save_result.setEnabled(False)
            #收起主窗口
            self.parent.mw.dock_result.close()
            self.parent.isdock = False