Exemple #1
0
    def __init__(self, data, radius=15):

        self.data = data

        # Add circular node
        self.node = QGraphicsEllipseItem(0, 0, 1, 1)

        # Set radius
        self.radius = radius

        # Add text label
        self.label = QGraphicsTextItem(data.label)
        font = self.label.font()
        font.setPointSize(10)
        self.label.setFont(font)

        # Add line between label and node
        self.line1 = QGraphicsLineItem(0, 0, 1, 1)
        self.line2 = QGraphicsLineItem(0, 0, 1, 1)

        self.node.setZValue(20)
        self.label.setZValue(10)
        self.line1.setZValue(10)
        self.line2.setZValue(10)

        self.line1.setPen(get_pen('0.5'))
        self.line2.setPen(get_pen('0.5'))

        self.color = '0.8'
Exemple #2
0
    def __init__(self, data, radius=15):

        self.data = data

        # Add circular node
        self.node = QGraphicsEllipseItem(0, 0, 1, 1)

        # Set radius
        self.radius = radius

        # Add text label
        self.label = QGraphicsTextItem(data.label)
        font = self.label.font()
        font.setPointSize(10)
        self.label.setFont(font)

        # Add line between label and node
        self.line1 = QGraphicsLineItem(0, 0, 1, 1)
        self.line2 = QGraphicsLineItem(0, 0, 1, 1)

        self.node.setZValue(20)
        self.label.setZValue(10)
        self.line1.setZValue(10)
        self.line2.setZValue(10)

        self.line1.setPen(get_pen('0.5'))
        self.line2.setPen(get_pen('0.5'))

        self.color = '0.8'
Exemple #3
0
    def setAngledTexts(self, angledTexts: List[AngledText]) -> None:
        self._angledTexts = angledTexts

        self._lineItems.clear()
        self._textItems.clear()

        scene: QGraphicsScene = self.scene()
        for item in self.childItems():
            item: QGraphicsItem = item
            self.removeFromGroup(item)
            if scene is not None:
                scene.removeItem(item)

        for angledText in self._angledTexts:
            lineItem = QGraphicsLineItem(self.parentItem())
            self.addToGroup(lineItem)
            self._lineItems.append(lineItem)

            textItem = QGraphicsTextItem(self.parentItem())
            textItem.setPlainText(angledText.text)
            self.addToGroup(textItem)
            self._textItems.append(textItem)
Exemple #4
0
    def __init__(self,
                 port_id: str,
                 text: str = 'port',
                 content: Any = None,
                 port_type='input'):
        super(CustomPort, self).__init__()
        self.setAcceptHoverEvents(True)  # 接受鼠标悬停事件
        self.relative_pos = (0, 0)
        self.color = COLOR_NORMAL
        self.id = port_id
        self.text = text
        self.size = (10, 10)
        self.content = content
        self.connected_lines = []
        self.canvas = None
        self.node: 'Node' = None

        self.text_item = QGraphicsTextItem(parent=self)
        self.port_type = port_type
        if port_type == 'input':
            self.text_item.setPos(10, -5)
        else:
            self.text_item.setPos(-30, -5)
        self.text_item.setPlainText(self.text)
Exemple #5
0
    def __init__(self,
                 canvas: 'PMGraphicsScene',
                 node_id,
                 text: str = '',
                 input_ports: List[CustomPort] = None,
                 output_ports: List[CustomPort] = None,
                 icon_path=r'',
                 look: Dict[str, str] = None):
        super(Node, self).__init__()
        assert isinstance(look, dict)
        self.look = look
        direction = self.look.get('direction')
        self.direction = 'E' if direction is None else direction  # 输出端口的方向
        assert_in(self.direction, ['E', 'W'])
        self.look['direction'] = self.direction

        self.id = node_id
        self.text = text if text != '' else node_id
        self.base_rect = CustomRect(self)

        icon_path = os.path.join(get_parent_path(__file__), 'icons',
                                 'logo.png') if icon_path == '' else icon_path
        self.icon_path = icon_path
        pix_map = QPixmap(icon_path)
        self.pix_map_item = QGraphicsPixmapItem(pix_map, parent=self.base_rect)
        self.pix_map_item.setPos(20, 20)

        self.text_item = QGraphicsTextItem(parent=self.base_rect)

        start_left = 50
        self.text_item.setPos(start_left, 10)
        self.text_item.setPlainText(self.text)

        self.internal_value_text = QGraphicsTextItem(parent=self.base_rect)
        self.internal_value_text.setPos(start_left, 30)
        self.internal_value_text.setPlainText('')

        self.status_text = QGraphicsTextItem(parent=self.base_rect)
        self.status_text.setPos(start_left, 100)
        self.status_text.setPlainText('wait')

        self.input_ports = input_ports
        self.output_ports = output_ports

        self.input_ports_dic = {p.id: p for p in input_ports}
        self.output_ports_dic = {p.id: p for p in output_ports}
        self.canvas = canvas
        # self.set_content(content)
        self.setup()
Exemple #6
0
class DataNode:
    def __init__(self, data, radius=15):

        self.data = data

        # Add circular node
        self.node = QGraphicsEllipseItem(0, 0, 1, 1)

        # Set radius
        self.radius = radius

        # Add text label
        self.label = QGraphicsTextItem(data.label)
        font = self.label.font()
        font.setPointSize(10)
        self.label.setFont(font)

        # Add line between label and node
        self.line1 = QGraphicsLineItem(0, 0, 1, 1)
        self.line2 = QGraphicsLineItem(0, 0, 1, 1)

        self.node.setZValue(20)
        self.label.setZValue(10)
        self.line1.setZValue(10)
        self.line2.setZValue(10)

        self.line1.setPen(get_pen('0.5'))
        self.line2.setPen(get_pen('0.5'))

        self.color = '0.8'

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        self._radius = value
        self.node.setRect(-value, -value, 2 * value, 2 * value)

    def contains(self, point):

        # Check label
        if self.label.contains(self.label.mapFromScene(point)):
            return True

        # Check node
        if self.node.contains(self.node.mapFromScene(point)):
            return True

        return False

    def update(self):
        self.node.update()

    def add_to_scene(self, scene):
        scene.addItem(self.node)
        scene.addItem(self.label)
        scene.addItem(self.line1)
        scene.addItem(self.line2)

    def remove_from_scene(self, scene):
        scene.removeItem(self.node)
        scene.removeItem(self.label)
        scene.removeItem(self.line1)
        scene.removeItem(self.line2)

    @property
    def node_position(self):
        pos = self.node.pos()
        return pos.x(), pos.y()

    @node_position.setter
    def node_position(self, value):
        self.node.setPos(value[0], value[1])
        self.update_lines()

    @property
    def label_position(self):
        pos = self.label.pos()
        return pos.x(), pos.y()

    @label_position.setter
    def label_position(self, value):
        self.label.setPos(value[0], value[1])
        self.update_lines()

    def update_lines(self):
        x0, y0 = self.label_position
        x2, y2 = self.node_position
        x1 = 0.5 * (x0 + x2)
        y1 = y0
        self.line1.setLine(x0, y0, x1, y1)
        self.line2.setLine(x1, y1, x2, y2)

    @property
    def color(self):
        return qt_to_mpl_color(self.node.brush().color())

    @color.setter
    def color(self, value):
        self.node.setBrush(mpl_to_qt_color(value))
Exemple #7
0
class Node(QObject):
    """
    Node是一个节点的抽象
    """
    def __init__(self,
                 canvas: 'PMGraphicsScene',
                 node_id,
                 text: str = '',
                 input_ports: List[CustomPort] = None,
                 output_ports: List[CustomPort] = None,
                 icon_path=r'',
                 look: Dict[str, str] = None):
        super(Node, self).__init__()
        assert isinstance(look, dict)
        self.look = look
        direction = self.look.get('direction')
        self.direction = 'E' if direction is None else direction  # 输出端口的方向
        assert_in(self.direction, ['E', 'W'])
        self.look['direction'] = self.direction

        self.id = node_id
        self.text = text if text != '' else node_id
        self.base_rect = CustomRect(self)

        icon_path = os.path.join(get_parent_path(__file__), 'icons',
                                 'logo.png') if icon_path == '' else icon_path
        self.icon_path = icon_path
        pix_map = QPixmap(icon_path)
        self.pix_map_item = QGraphicsPixmapItem(pix_map, parent=self.base_rect)
        self.pix_map_item.setPos(20, 20)

        self.text_item = QGraphicsTextItem(parent=self.base_rect)

        start_left = 50
        self.text_item.setPos(start_left, 10)
        self.text_item.setPlainText(self.text)

        self.internal_value_text = QGraphicsTextItem(parent=self.base_rect)
        self.internal_value_text.setPos(start_left, 30)
        self.internal_value_text.setPlainText('')

        self.status_text = QGraphicsTextItem(parent=self.base_rect)
        self.status_text.setPos(start_left, 100)
        self.status_text.setPlainText('wait')

        self.input_ports = input_ports
        self.output_ports = output_ports

        self.input_ports_dic = {p.id: p for p in input_ports}
        self.output_ports_dic = {p.id: p for p in output_ports}
        self.canvas = canvas
        # self.set_content(content)
        self.setup()

    def display_internal_values(self, val_str: str = ''):
        self.internal_value_text.setPlainText(val_str)

    def set_content(self, content: 'FlowContentEditableFunction' = None):
        self.content: 'FlowContentEditableFunction' = content if content is not None else FlowContentEditableFunction(
            self, '')
        self.content.signal_exec_finished.connect(self.on_exec_finished)
        self.content.signal_exec_started.connect(self.on_exec_started)
        self.content.signal_error_occurs.connect(self.on_error_occurs)
        self.display_internal_values(self.content.format_param())

    def on_error_occurs(self, error: FlowContentError):
        flow_widget: PMFlowWidget = self.canvas.flow_widget
        flow_widget.on_error_occurs(error)

    def on_exec_started(self, content):
        """
        执行前进行的操作
        :param content:
        :return:
        """
        self.status_text.setPlainText(content)

    def on_exec_finished(self, content: str):
        """
        执行完成后进行的操作
        :param content:
        :return:
        """
        self.status_text.setPlainText(content)

    #
    def reset(self):
        self.status_text.setPlainText('wait')

    def get_port_index(self, port: CustomPort):
        """
        获取端口的索引
        :param port:
        :return:
        """
        return self.input_ports.index(
            port) if port.port_type == 'input' else self.output_ports.index(
                port)

    def set_icon(self, icon_path: str):
        pass

    def set_pos(self, x: int, y: int):
        """
        设置位置,左上角角点
        :param x:
        :param y:
        :return:
        """
        self.base_rect.setPos(x, y)
        self.refresh_pos()

    def get_pos(self) -> Tuple[int, int]:
        """
        获取位置,左上角角点
        :return:
        """
        pos = self.base_rect.pos()
        return pos.x(), pos.y()

    def refresh_pos(self):
        """
        刷新位置。当节点被拖动的时候,此方法会被触发。
        """
        y = self.base_rect.y()
        dy_input = self.base_rect.boundingRect().height() / (
            1 + len(self.input_ports))
        dy_output = self.base_rect.boundingRect().height() / (
            1 + len(self.output_ports))
        if self.direction == 'E':
            x_input = self.base_rect.x() + 5
            x_output = self.base_rect.x() + self.base_rect.boundingRect(
            ).width() - 15
        elif self.direction == 'W':
            x_input = self.base_rect.x() + self.base_rect.boundingRect().width(
            ) - 15
            x_output = self.base_rect.x() + 5
        else:
            raise NotImplementedError
        for i, p in enumerate(self.input_ports):
            p.setPos(QPointF(x_input, y + int(dy_input * (1 + i))))
        for i, p in enumerate(self.output_ports):
            p.setPos(QPointF(x_output, y + int(dy_output * (1 + i))))
        self.canvas.signal_item_dragged.emit('')

    def setup(self):
        self.base_rect.setPos(80, 80)
        self.canvas.signal_clear_selection.connect(
            self.base_rect.on_clear_selection)
        self.canvas.addItem(self.base_rect)
        for p in self.input_ports + self.output_ports:
            self.canvas.addItem(p)
            p.port_clicked.connect(self.on_port_clicked)
            p.node = self
        self.refresh_pos()

    def on_port_clicked(self, port: 'CustomPort'):

        if self.canvas.drawing_lines:
            if self.canvas.line_start_port is not port:
                if not port.port_type == self.canvas.line_start_port.port_type:
                    if self.canvas.allow_multiple_input or (
                        (not self.canvas.allow_multiple_input)
                            and len(port.connected_lines) == 0):
                        self.canvas.connect_port(port)

        else:
            if port.port_type == 'output':
                self.canvas.drawing_lines = True
                # if self.canvas.item

                self.canvas.line_start_point = port.center_pos
                self.canvas.line_start_port = port

    def on_delete(self):
        for port in self.input_ports + self.output_ports:
            port.canvas = self.canvas
            port.on_delete()
        self.canvas.removeItem(self.base_rect)
        self.canvas.nodes.remove(self)
        self.deleteLater()

    def __repr__(self):
        s = super(Node, self).__repr__()
        return s + repr(self.input_ports) + repr(self.output_ports)

    def get_port(self, port_id: str) -> 'CustomPort':
        for port in self.input_ports + self.output_ports:
            if port_id == port.id:
                return port
        return None

    def add_port(self, port: CustomPort):
        """
        添加一个端口
        :param port:
        :return:
        """

        port_type = port.port_type
        if port_type == 'input':
            self.input_ports.append(port)
            self.input_ports_dic[port.id] = port
        elif port_type == 'output':
            self.output_ports.append(port)
            self.output_ports_dic[port.id] = port
        else:
            raise ValueError('port type invalid')
        if port.node is None:
            port.node = self
        self.refresh_pos()
        self.canvas.addItem(port)
        port.port_clicked.connect(self.on_port_clicked)

        return port

    def remove_port(self, port: CustomPort):
        """
        删除一个端口
        :param port:
        :return:
        """

        port_type = port.port_type
        if port_type == 'input':
            self.input_ports.remove(port)
            self.input_ports_dic.pop(port.id)
        elif port_type == 'output':
            self.output_ports.remove(port)
            self.output_ports_dic.pop(port.id)
        else:
            raise ValueError('port type invalid')

        port.on_delete()
        self.refresh_pos()

    def change_property(self, property: Dict[str, Union[int, str]]):
        """
        改变各个端口的文字、端口的数目以及文字。
        :param property:
        :return:
        """
        self.text = property['text']
        self.text_item.setPlainText(self.text)
        self.content.update_settings(property)
        self.valid_port_ids = []
        if property.get('inputs') is not None:
            for input_id, input_text in zip(property['inputs'][0],
                                            property['inputs'][1]):
                self.valid_port_ids.append(input_id)
                p = self.get_port(input_id)
                if p is None:
                    p = self.add_port(
                        CustomPort(port_id=input_id,
                                   text=input_text,
                                   port_type='input'))
                p.set_text(input_text)
            for p in self.input_ports:
                if p.id not in self.valid_port_ids:
                    self.remove_port(p)

        if property.get('outputs') is not None:
            for output_id, output_text in zip(property['outputs'][0],
                                              property['outputs'][1]):
                self.valid_port_ids.append(output_id)
                p = self.get_port(output_id)
                if p is None:
                    p = self.add_port(
                        CustomPort(port_id=output_id,
                                   text=output_text,
                                   port_type='output'))
                p.set_text(output_text)

            for p in self.output_ports:
                if p.id not in self.valid_port_ids:
                    self.remove_port(p)

    def change_ports_property(self, property: Dict[str, Union[int, str]]):
        """
        改变各个端口的文字、端口的数目以及文字。
        :param property:
        :return:
        """
        self.text = property['text']
        self.text_item.setPlainText(self.text)
        self.valid_port_ids = []
        if property.get('inputs') is not None:
            for input_id, input_text in zip(property['inputs'][0],
                                            property['inputs'][1]):
                self.valid_port_ids.append(input_id)
                p = self.get_port(input_id)
                if p is None:
                    p = self.add_port(
                        CustomPort(port_id=input_id,
                                   text=input_text,
                                   port_type='input'))
                p.set_text(input_text)
            for p in self.input_ports:
                if p.id not in self.valid_port_ids:
                    self.remove_port(p)

        if property.get('outputs') is not None:
            for output_id, output_text in zip(property['outputs'][0],
                                              property['outputs'][1]):
                self.valid_port_ids.append(output_id)
                p = self.get_port(output_id)
                if p is None:
                    p = self.add_port(
                        CustomPort(port_id=output_id,
                                   text=output_text,
                                   port_type='output'))
                p.set_text(output_text)

            for p in self.output_ports:
                if p.id not in self.valid_port_ids:
                    self.remove_port(p)

    def on_edit_ports(self):
        from pmgwidgets import PMGPanel
        from qtpy.QtWidgets import QDialog, QVBoxLayout
        dlg = QDialog(self.base_rect.scene().flow_widget)
        sp = PMGPanel()
        p: 'CustomPort' = None
        input_ids, output_ids = [], []
        input_texts, output_texts = [], []
        self._last_var = 0

        def new_id_input():
            node_id = self.id
            max_val = 0
            for p in self.input_ports:
                n, t, p = p.parse_id()
                if max_val < int(p):
                    max_val = int(p)
            self._last_var += 1
            return '%s:input:%d' % (node_id, max_val + self._last_var)

        def new_id_output():
            node_id = self.id
            max_val = 0
            for p in self.output_ports:
                n, t, p = p.parse_id()
                if max_val < int(p):
                    max_val = int(p)
            self._last_var += 1
            return '%s:output:%d' % (node_id, max_val + self._last_var)

        for p in self.input_ports:
            input_ids.append(p.id)
            input_texts.append(p.text)

        for p in self.output_ports:
            output_ids.append(p.id)
            output_texts.append(p.text)

        views = []
        # views += self.content.get_settings_params()
        views += [
            ('line_ctrl', 'text', 'Node Text', self.text),
        ]
        if self.content.ports_changable[0]:
            views.append(('list_ctrl', 'inputs', 'Set Inputs',
                          [input_ids, input_texts], new_id_input))
        if self.content.ports_changable[1]:
            views.append(('list_ctrl', 'outputs', 'Set Outputs',
                          [output_ids, output_texts], new_id_output))
        sp.set_items(views)
        dlg.setLayout(QVBoxLayout())
        dlg.layout().addWidget(sp)
        dlg.exec_()

        dic = sp.get_value()
        self.change_ports_property(dic)

    def on_edit_properties_requested(self):
        """
        Show Settings Panel.
        If It was customized node,it will call the function of the content.
        Or the default settings parameters will be got.
        Returns:

        """
        from pmgwidgets import PMGPanel
        from qtpy.QtWidgets import QDialog, QVBoxLayout

        if isinstance(self.content, FlowContentForFunction):
            dlg = QDialog(self.base_rect.scene().flow_widget)
            sp = PMGPanel()
            p: 'CustomPort' = None
            input_ids, output_ids = [], []
            input_texts, output_texts = [], []
            self._last_var = 0

            def new_id_input():
                node_id = self.id
                max_val = 0
                for p in self.input_ports:
                    n, t, p = p.parse_id()
                    if max_val < int(p):
                        max_val = int(p)
                self._last_var += 1
                return '%s:input:%d' % (node_id, max_val + self._last_var)

            def new_id_output():
                node_id = self.id
                max_val = 0
                for p in self.output_ports:
                    n, t, p = p.parse_id()
                    if max_val < int(p):
                        max_val = int(p)
                self._last_var += 1
                return '%s:output:%d' % (node_id, max_val + self._last_var)

            for p in self.input_ports:
                input_ids.append(p.id)
                input_texts.append(p.text)

            for p in self.output_ports:
                output_ids.append(p.id)
                output_texts.append(p.text)

            views = []
            views += self.content.get_settings_params()
            views += [
                ('line_ctrl', 'text', 'Node Text', self.text),
            ]
            if self.content.ports_changable[0]:
                views.append(('list_ctrl', 'inputs', 'Set Inputs',
                              [input_ids, input_texts], new_id_input))
            if self.content.ports_changable[1]:
                views.append(('list_ctrl', 'outputs', 'Set Outputs',
                              [output_ids, output_texts], new_id_output))
            sp.set_items(views)
            dlg.setLayout(QVBoxLayout())
            dlg.layout().addWidget(sp)
            dlg.exec_()

            dic = sp.get_value()
            self.change_property(dic)
        else:
            try:
                self.content.settings_window_requested(self.canvas.flow_widget)
            except Exception as e:
                import traceback
                exc = traceback.format_exc()
                print(exc)
                QMessageBox.warning(self.canvas.flow_widget, 'Error', str(e))

    def invert(self):
        self.direction = 'W' if self.direction == 'E' else 'E'
        self.refresh_pos()
        self.look['direction'] = self.direction
Exemple #8
0
class DataNode:

    def __init__(self, data, radius=15):

        self.data = data

        # Add circular node
        self.node = QGraphicsEllipseItem(0, 0, 1, 1)

        # Set radius
        self.radius = radius

        # Add text label
        self.label = QGraphicsTextItem(data.label)
        font = self.label.font()
        font.setPointSize(10)
        self.label.setFont(font)

        # Add line between label and node
        self.line1 = QGraphicsLineItem(0, 0, 1, 1)
        self.line2 = QGraphicsLineItem(0, 0, 1, 1)

        self.node.setZValue(20)
        self.label.setZValue(10)
        self.line1.setZValue(10)
        self.line2.setZValue(10)

        self.line1.setPen(get_pen('0.5'))
        self.line2.setPen(get_pen('0.5'))

        self.color = '0.8'

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        self._radius = value
        self.node.setRect(-value, -value, 2 * value, 2 * value)

    def contains(self, point):

        # Check label
        if self.label.contains(self.label.mapFromScene(point)):
            return True

        # Check node
        if self.node.contains(self.node.mapFromScene(point)):
            return True

        return False

    def update(self):
        self.node.update()

    def add_to_scene(self, scene):
        scene.addItem(self.node)
        scene.addItem(self.label)
        scene.addItem(self.line1)
        scene.addItem(self.line2)

    def remove_from_scene(self, scene):
        scene.removeItem(self.node)
        scene.removeItem(self.label)
        scene.removeItem(self.line1)
        scene.removeItem(self.line2)

    @property
    def node_position(self):
        pos = self.node.pos()
        return pos.x(), pos.y()

    @node_position.setter
    def node_position(self, value):
        self.node.setPos(value[0], value[1])
        self.update_lines()

    @property
    def label_position(self):
        pos = self.label.pos()
        return pos.x(), pos.y()

    @label_position.setter
    def label_position(self, value):
        self.label.setPos(value[0], value[1])
        self.update_lines()

    def update_lines(self):
        x0, y0 = self.label_position
        x2, y2 = self.node_position
        x1 = 0.5 * (x0 + x2)
        y1 = y0
        self.line1.setLine(x0, y0, x1, y1)
        self.line2.setLine(x1, y1, x2, y2)

    @property
    def color(self):
        return qt_to_mpl_color(self.node.brush().color())

    @color.setter
    def color(self, value):
        self.node.setBrush(mpl_to_qt_color(value))
Exemple #9
0
 def select_next(self, source: QtWidgets.QGraphicsTextItem):
     text_item: pg.TextItem = source.parentItem()
     index = self.names.index(text_item)
     new_index = (index + 1) % len(self.names)
     source.clearFocus()
     self.focusNew(new_index)
Exemple #10
0
class CustomPort(QGraphicsObject):
    port_clicked = Signal(QGraphicsObject)

    def __init__(self,
                 port_id: str,
                 text: str = 'port',
                 content: Any = None,
                 port_type='input'):
        super(CustomPort, self).__init__()
        self.setAcceptHoverEvents(True)  # 接受鼠标悬停事件
        self.relative_pos = (0, 0)
        self.color = COLOR_NORMAL
        self.id = port_id
        self.text = text
        self.size = (10, 10)
        self.content = content
        self.connected_lines = []
        self.canvas = None
        self.node: 'Node' = None

        self.text_item = QGraphicsTextItem(parent=self)
        self.port_type = port_type
        if port_type == 'input':
            self.text_item.setPos(10, -5)
        else:
            self.text_item.setPos(-30, -5)
        self.text_item.setPlainText(self.text)

    def set_text(self, text: str):
        self.text_item.setPlainText(text)
        self.text = text

    def boundingRect(self):
        return QRectF(0, 0, self.size[0], self.size[1])

    @property
    def center_pos(self):
        return QPointF(self.x() + self.size[0] / 2,
                       self.y() + self.size[1] / 2)

    def paint(self, painter, styles, widget=None):
        pen1 = QPen(Qt.SolidLine)
        pen1.setColor(QColor(128, 128, 128))
        painter.setPen(pen1)

        brush1 = QBrush(Qt.SolidPattern)
        brush1.setColor(self.color)
        painter.setBrush(brush1)

        painter.setRenderHint(QPainter.Antialiasing)  # 反锯齿
        painter.drawRoundedRect(self.boundingRect(), 10, 10)

    def hoverEnterEvent(self, event: 'QGraphicsSceneHoverEvent') -> None:
        self.color = COLOR_HOVER_PORT
        self.update()

    def hoverLeaveEvent(self, event: 'QGraphicsSceneHoverEvent') -> None:
        self.color = COLOR_NORMAL
        self.update()

    def mousePressEvent(self, evt: QGraphicsSceneMouseEvent):
        if evt.button() == Qt.LeftButton:
            pos = (evt.scenePos().x(), evt.scenePos().y())
            self.relative_pos = (pos[0] - self.x(), pos[1] - self.y())
            self.port_clicked.emit(self)
        elif evt.button() == Qt.RightButton:
            pass
        elif evt.button() == Qt.MidButton:
            pass

    def paintEvent(self, paint_event):
        pen1 = QPen()
        pen1.setColor(QColor(166, 66, 250))
        painter = QPainter(self)
        painter.setPen(pen1)
        painter.begin(self)
        painter.drawRoundedRect(self.boundingRect(), 10, 10)  # 绘制函数
        painter.end()

    def get_pos(self) -> Tuple[int, int]:
        pos = self.pos()
        return pos.x(), pos.y()

    def get_connected_lines(self) -> List['CustomLine']:
        if len(self.connected_lines) == 0:
            return []
        else:
            return self.connected_lines

    def get_connected_port(self) -> List['CustomPort']:
        """
        获取连接的节点
        :return:
        """
        lines = self.get_connected_lines()
        if len(lines) == 0:
            return []
        port_list = []
        for l in lines:
            port_list.append(l.get_opposite_port(self))
        return port_list

    def on_delete(self):
        for line in self.connected_lines:
            line.on_delete()
        self.scene().removeItem(self)

    def parse_id(self) -> Tuple[str, str, str]:
        """
        解析id。id由三个元素构成,由冒号分割。
        如3:input:2,意思就是id3为3的节点中,id为2的输入端口。注意
        :return:
        """
        node_id, type, port_id = self.id.split(':')
        return node_id, type, port_id

    def __repr__(self):
        return super(CustomPort, self).__repr__() + 'id = ' + str(self.id)
Exemple #11
0
    def _to_qgraphicstextitem(self):

        t = QGraphicsTextItem()
        t.setDefaultTextColor(QColor(self.color.hexcolor))
        if self.html:
            text = self.text.replace(u'\n', u'<br />')
            t.setHtml(u'<div align="center">%s</div>' %
                      text if self.center else text)
        else:
            t.setPlainText(self.text)
        mw = self.max_width
        if mw is None:
            if self.uniform_coordinates:
                mw = self._canvas.width // 2 - self.x
            else:
                mw = self._canvas.width - self.x
        if self.center:
            mw *= 2
        t.setTextWidth(mw)
        f = QFont(self.font_family,
                  weight=QFont.Bold if self.font_bold else QFont.Normal,
                  italic=self.font_italic)
        for family, substitute in font_substitutions:
            f.insertSubstitution(substitute, family)
        f.setPixelSize(self.font_size)
        t.setFont(f)
        return t