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))
class DualColoredLineSegment(QGraphicsItemGroup): """ One individual line segment. This is a group because it needs to create two lines in order to create a multi colored dashed pattern. Attributes: spacing (int): how much space in pixels are between each line segment """ def __init__(self, parent=None, width=1, color1=QColor(0, 0, 0), color2=QColor(255, 255, 255)): super(DualColoredLineSegment, self).__init__(parent) # create lines self.line_1 = QGraphicsLineItem() self.line_2 = QGraphicsLineItem() self.width = width self._length = 2 self._spacing = 5 # set pen self.setColor1(color1) self.setColor2(color2) # add lines to group self.addToGroup(self.line_1) self.addToGroup(self.line_2) """ DISPLAY""" def setColor1(self, color): """ Sets the first line to the specified color Args: color (QColor): color for the line to be set to """ pen = self.createPen(color) self.line_1.setPen(pen) def setColor2(self, color): """ Sets the first line to the specified color Args: color (QColor): color for the line to be set to """ pen = self.createPen(color, offset=True) self.line_2.setPen(pen) def updatePen(self): for line in [self.line_1, self.line_2]: pen = line.pen() total_line_space = self.length() + (2 * self.spacing()) pen.setDashPattern([self.length(), total_line_space]) pen.setWidth(self.width) line.setPen(pen) def createPen(self, color, offset=None): """ Creates a pen of the color specified Args: color (QColor): color for the line to be set to offset (bool): if color should be offset or not. Since this is only two colors, this can be a boolean, rather than an index. """ pen = QPen() pen.setColor(color) total_line_space = self.length() + (2 * self.spacing()) if offset: pen.setDashOffset(self.length() + self.spacing()) pen.setDashPattern([self.length(), total_line_space]) pen.setWidth(self.width) return pen def setLine(self, x, y, width, height): self.line_1.setLine(x, y, width, height) self.line_2.setLine(x, y, width, height) """ PROPERTIES """ def width(self): return self._width def setWidth(self, width): self._width = width def length(self): return self._length def setLength(self, length): self._length = length def spacing(self): return self._spacing def setSpacing(self, spacing): self._spacing = spacing