示例#1
0
 def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent):
     box = QRectF(self.buttonDownRect)
     pos = event.pos()
     offset = pos - event.buttonDownPos(Qt.LeftButton)
     if self.handleSelected is None:
         box.translate(offset)
         new_box = box
     elif self.handleSelected == 0:
         pos = box.topLeft() + offset
         new_size = box.bottomRight() - pos
         width = max(new_size.x(), 0)
         height = max(new_size.y(), 0)
         left = min(pos.x(), box.right())
         top = min(pos.y(), box.bottom())
         new_box = QRectF(left, top, width, height)
     elif self.handleSelected == 1:
         pos = box.topLeft() + offset
         height = max(box.bottom() - pos.y(), 0)
         top = min(pos.y(), box.bottom())
         new_box = QRectF(box.left(), top, box.width(), height)
     elif self.handleSelected == 2:
         pos = box.topRight() + offset
         top = min(pos.y(), box.bottom())
         width = max(pos.x() - box.left(), 0)
         height = max(box.bottom() - pos.y(), 0)
         new_box = QRectF(box.left(), top, width, height)
     elif self.handleSelected == 3:
         pos = box.topRight() + offset
         width = max(pos.x() - box.left(), 0)
         new_box = QRectF(box.left(), box.top(), width, box.height())
     elif self.handleSelected == 4:
         pos = box.bottomRight() + offset
         new_size = pos - box.topLeft()
         width = max(new_size.x(), 0)
         height = max(new_size.y(), 0)
         new_box = QRectF(box.left(), box.top(), width, height)
     elif self.handleSelected == 5:
         pos = box.bottomRight() + offset
         height = max(pos.y() - box.top(), 0)
         new_box = QRectF(box.left(), box.top(), box.width(), height)
     elif self.handleSelected == 6:
         pos = box.bottomLeft() + offset
         left = min(pos.x(), box.right())
         width = max(box.right() - pos.x(), 0)
         height = max(pos.y() - box.top(), 0)
         new_box = QRectF(left, box.top(), width, height)
     elif self.handleSelected == 7:
         pos = box.bottomLeft() + offset
         left = min(pos.x(), box.right())
         width = max(box.right() - pos.x(), 0)
         new_box = QRectF(left, box.top(), width, box.height())
     new_box = QRectF(round(new_box.left()), round(new_box.top()),
                      round(new_box.width()), round(new_box.height()))
     self.setRect(new_box)
     self.setHandlesPos()
     self.signalHandler.boxChanged.emit(self.tabIndex, self.rowIndex,
                                        new_box)
示例#2
0
 def get_points_rect(self):
     rect = QRectF()
     left = 1
     right = -1
     up = 1
     down = -1
     for p in self.points:
         if p.x() < left:
             left = p.x()
         if p.x() > right:
             right = p.x()
         if p.y() < up:
             up = p.y()
         if p.y() > down:
             down = p.y()
     rect.setLeft(left)
     rect.setRight(right)
     rect.setTop(up)
     rect.setBottom(down)
     self.width = rect.width()
     self.height = rect.height()
     # rect.setLeft(-self.width/2)
     # rect.setRight(self.width/2)
     # rect.setTop(-self.height/2)
     # rect.setBottom(self.height/2)
     return rect
示例#3
0
文件: drift.py 项目: djdt/pewpew
    def __init__(
        self,
        rect: QtCore.QRectF,
        px: float,
        py: float,
        trim_enabled: bool = False,
        parent: QtWidgets.QGraphicsItem = None,
    ):
        super().__init__(rect, parent=parent)

        pen = QtGui.QPen(QtCore.Qt.white, 2.0)
        pen.setCosmetic(True)
        self.setPen(pen)

        self.px = px
        self.py = py
        self.trim_enabled = trim_enabled

        self.top = rect.y() + rect.height() * 0.33
        self.top = self.top - self.top % py
        self.bottom = rect.y() + rect.height() * 0.66
        self.bottom = self.bottom - self.bottom % py

        self.changed = False
示例#4
0
    def get_points_rect(self):
        if len(self.points) == 0:
            return QRectF(0, 0, 0, 0)
        x_coords = [p.x() for p in self.points]
        y_coords = [p.y() for p in self.points]
        left = min(x_coords)
        right = max(x_coords)
        up = min(y_coords)
        down = max(y_coords)

        rect = QRectF(left, up, right - left, down - up)

        self.width = rect.width()
        self.height = rect.height()
        return rect
示例#5
0
 def show_all(self):
     # trick:
     # if user zoom in or zoom out too much view exceeds matrix limit
     # so need to set view's matrix to initial matrix
     self.setMatrix(self.initial_matrix)
     items = self.get_visible_items()
     rect = QRectF()
     for i in items:
         rect = rect.united(i.boundingRect())
     # it is not working properly without updating the rect
     # need to set new position and edit rect's size
     rect.setX(rect.x() - 1)
     rect.setY(rect.y() - 1)
     rect.setWidth(rect.width() + 1)
     rect.setHeight(rect.height() + 1)
     self.fitInView(rect, Qt.KeepAspectRatio)
    def draw_monitor_label(self, painter: QPainter, rect: QRectF, txt: str):
        painter.save()
        font = self.monitor_label_font
        font_metrics = QFontMetrics(font, painter.device())

        bounding_rect = font_metrics.boundingRect(rect.toRect(), 0, txt)
        x_factor = rect.width() / bounding_rect.width()
        y_factor = rect.height() / bounding_rect.height()
        factor = min(x_factor, y_factor)

        font.setPointSizeF(font.pointSizeF() * factor)
        painter.setFont(font)
        painter.setPen(self.monitor_label_font_color)

        painter.drawText(rect, Qt.AlignCenter, txt)
        painter.restore()
示例#7
0
    def on_target_viewport_visible_scene_rect_changed(self, visible: QRectF):
        scene = self._target_view.scene()
        if scene is None:
            return

        x = (visible.x() - scene.sceneRect().x()) * self._scale
        y = (visible.y() - scene.sceneRect().y()) * self._scale
        width = visible.width() * self._scale
        height = visible.height() * self._scale
        mm_scene_w = self.sceneRect().width()
        mm_scene_h = self.sceneRect().height()

        minimap_vp_rect = QRectF()
        minimap_vp_rect.setTopLeft(
            QPoint(int(clamp(x, 0, mm_scene_w)), int(clamp(y, 0, mm_scene_h))))
        minimap_vp_rect.setBottomRight(
            QPoint(int(clamp(x + width, 0, mm_scene_w)),
                   int(clamp(y + height, 0, mm_scene_h))))

        self._minimap_target_viewport_box.set_viewport_rect(minimap_vp_rect)
        self._minimap_target_viewport_box.update()
示例#8
0
    def reload_target_scene(self):
        """
        Reload scene from target view, scaling the minimap view to properly fit the scene into view while preserving
        scene aspect ratio.
        """
        scene = self._target_view.scene()
        if scene is None:
            return

        # Scale target scene dimensions to fit within widget bounds, preserving scene aspect ratio
        mm_max_w = self.maximumWidth()
        mm_max_h = self.maximumHeight()
        scene_rect = scene.sceneRect()
        scene_w = scene_rect.width()
        scene_h = scene_rect.height()

        if mm_max_w == 0 or mm_max_h == 0 or scene_w == 0 or scene_h == 0:
            return

        minimap_aspect_ratio = mm_max_w / mm_max_h
        scene_aspect_ratio = scene_w / scene_h

        if minimap_aspect_ratio < scene_aspect_ratio:
            self._scale = mm_max_w / scene_w
        else:
            self._scale = mm_max_h / scene_h

        scaled_scene_rect = QRectF(0, 0, int(scene_w * self._scale),
                                   int(scene_h * self._scale))
        self.resize(scaled_scene_rect.width(), scaled_scene_rect.height())
        self._minimap_scene.setSceneRect(scaled_scene_rect)
        self.setSceneRect(scaled_scene_rect)
        self._minimap_target_scene_viewer.set_scene_rect(scaled_scene_rect)
        self._minimap_target_viewport_box.set_scene_rect(scaled_scene_rect)

        self._minimap_target_scene_viewer.update_scene_drawing()
        self.on_target_viewport_visible_scene_rect_changed(
            self._target_view.visible_scene_rect)
示例#9
0
 def drawCropTool(self, img):
     """
     Draws the 8 crop buttons around the displayed image,
     with their current margins.
     @param img:
     @type img: QImage
     """
     r = self.parent().img.resize_coeff(self.parent())
     self.formFactor = img.height() / img.width()
     left = self.btnDict['left']
     top = self.btnDict['top']
     bottom = self.btnDict['bottom']
     right = self.btnDict['right']
     # cRect = QRect(round(left.margin), round(top.margin), img.width() - round(right.margin + left.margin),
     # img.height() - round(bottom.margin + top.margin))
     cRect = QRectF(left.margin, top.margin,
                    img.width() - right.margin - left.margin,
                    img.height() - bottom.margin - top.margin)
     p = cRect.topLeft() * r + QPoint(img.xOffset, img.yOffset)
     x, y = p.x(), p.y()
     w, h = cRect.width() * r, cRect.height() * r
     left.move(x - left.width(), y + h // 2)
     right.move(x + w, y + h // 2)
     top.move(x + w // 2, y - top.height())
     bottom.move(x + w // 2, y + h)
     topLeft = self.btnDict['topLeft']
     topLeft.move(x - topLeft.width(), y - topLeft.height())
     topRight = self.btnDict['topRight']
     topRight.move(x + w, y - topRight.height())
     bottomLeft = self.btnDict['bottomLeft']
     bottomLeft.move(x - bottomLeft.width(), y + h)
     bottomRight = self.btnDict['bottomRight']
     bottomRight.move(x + w, y + h)
     self.crWidth, self.crHeight = img.width() - int(img.cropLeft) - int(
         img.cropRight), img.height() - int(img.cropTop) - int(
             img.cropBottom)
示例#10
0
文件: color.py 项目: IvanKosik/vision
class ColorTransferFunctionViewer(DataViewer):
    def __init__(self, data: ColorTransferFunction = None):
        super().__init__(data)

        self.chart = ColorTransferFunctionChart(data)
        # self.chart.legend().hide()
        self.chart_rect_f = QRectF()

        self.axis_x = QtCharts.QValueAxis()
        # self.axis_x.setLabelFormat('%d')
        self.axis_x.setLabelFormat('%.1f')
        self.axis_x.setTitleText('Intensity')
        self.chart.addAxis(self.axis_x, Qt.AlignBottom)

        self.axis_y = QtCharts.QValueAxis()
        # self.axis_y.setTickCount(10)
        self.axis_y.setLabelFormat('%.2f')
        # self.axis_y.setTitleText('Magnitude')
        self.chart.addAxis(self.axis_y, Qt.AlignLeft)

        self.axis_x.setRange(0, self.data.points[-1].x)
        self.axis_y.setRange(0, 1)
        # Add an empty series, else |chart.mapToPosition| will no work
        self.series = self.add_series()

        self.chart_view = QtCharts.QChartView(self.chart)
        # self.chart_view.setRubberBand(QtCharts.QChartView.RectangleRubberBand)
        self.chart_view.setRenderHint(QPainter.Antialiasing)

        self.scene = self.chart_view.scene()

        self._interval_views = SortedList()
        self._point_views = []
        if self.data is not None:
            self._add_interval_views()
            self._add_point_views()

        self.data.point_added.connect(self._on_point_added)

        grid_layout = QGridLayout()
        grid_layout.setContentsMargins(0, 0, 0, 0)
        grid_layout.addWidget(self.chart_view)
        self.setLayout(grid_layout)

    def _add_interval_views(self):
        for point, next_point in pairwise(self.data.points):
            if next_point is not None:
                self._add_interval_view(point, next_point)

    def _add_interval_view(self, begin_point: ColorTransferFunctionPoint, end_point: ColorTransferFunctionPoint) \
            -> ColorTransferFunctionIntervalView:
        interval_view = ColorTransferFunctionIntervalView(
            self, begin_point, end_point, self.chart)
        interval_view.setZValue(10)  # To display item on top of chart grid
        self.scene.addItem(interval_view)
        self._interval_views.add(interval_view)
        return interval_view

    def _add_point_views(self):
        for point in self.data.points:
            self._add_point_view(point)

    def _add_point_view(
            self, point: ColorTransferFunctionPoint
    ) -> ColorTransferFunctionPointView:
        point_view = ColorTransferFunctionPointView(self, point, self.chart)
        point_view.setZValue(
            11)  # To display item on top of chart grid and interval views
        self.scene.addItem(point_view)
        self._point_views.append(point_view)
        return point_view

    def _update_chart_size(self):
        top_left_pos = self.chart.mapToPosition(
            QPointF(self.axis_x.min(), self.axis_y.max()))
        bottom_right_pos = self.chart.mapToPosition(
            QPointF(self.axis_x.max(), self.axis_y.min()))
        self.chart_rect_f = QRectF(top_left_pos, bottom_right_pos)

    def _on_point_added(self, point: ColorTransferFunctionPoint):
        self._add_point_view(point)

        # Update existed interval views
        point_index = self.data.points.index(point)
        if 0 < point_index < len(
                self.data.points
        ) - 1:  # Only if point was added between other existed points
            # Exclude cases, where point was added before first and after last points
            before_point_index = point_index - 1
            before_point_interval = self._interval_views[before_point_index]
            before_point_interval.end_point = point
            before_point_interval.update()

        # Add new interval view
        if point_index == len(
                self.data.points
        ) - 1:  # If was added last point (point after last interval)
            new_interval_view = self._add_interval_view(
                self.data.point_before(point), point)
            new_interval_view.update()
        else:
            new_interval_view = self._add_interval_view(
                point, self.data.point_after(point))
            new_interval_view.update()

    def resizeEvent(self, resize_event: QResizeEvent):
        self._update_chart_size()

        # min_tick_count = self.axis_x.max() - self.axis_x.min() + 1
        # tick_count = min(min_tick_count, self.width() / 50)
        tick_count = self.chart_rect_f.width() / 50
        self.axis_x.setTickCount(round(tick_count))

        self.axis_y.setTickCount(round(self.chart_rect_f.height() / 20))

        for interval_view in self._interval_views:
            interval_view.update()
        for point_view in self._point_views:
            point_view.update_size()
            point_view.update_pos()

    def add_series(self):
        series = QtCharts.QLineSeries()
        series.setName('Color Transfer Function')
        self.chart.addSeries(series)
        series.attachAxis(self.axis_x)
        series.attachAxis(self.axis_y)
        return series
示例#11
0
class Callout(QGraphicsItem):
    """
        This class code was taken from \
        https://code.qt.io/cgit/qt/qtcharts.git/tree/examples/charts/callout/callout.cpp?h=5.13
    """
    def __init__(self, chart):
        QGraphicsItem.__init__(self, chart)

        self.chart = chart
        self.rect = QRectF()
        self.anchor = QPointF()
        self.text_rect = QRectF()
        self.text = ""
        self.font = QFont()

    def boundingRect(self):
        anchor = self.mapFromParent(self.chart.mapToPosition(self.anchor))

        rect = QRectF()

        rect.setLeft(min(self.rect.left(), anchor.x()))
        rect.setRight(max(self.rect.right(), anchor.x()))
        rect.setTop(min(self.rect.top(), anchor.y()))
        rect.setBottom(max(self.rect.bottom(), anchor.y()))

        return rect

    def paint(self, painter, option, widget):
        path = QPainterPath()

        path.addRoundedRect(self.rect, 5, 5)

        anchor = self.mapFromParent(self.chart.mapToPosition(self.anchor))

        if not self.rect.contains(anchor):
            point1 = QPointF()
            point2 = QPointF()

            # establish the position of the anchor point in relation to m_rect
            above = anchor.y() <= self.rect.top()
            aboveCenter = anchor.y() > self.rect.top() and anchor.y(
            ) <= self.rect.center().y()
            belowCenter = anchor.y() > self.rect.center().y() and anchor.y(
            ) <= self.rect.bottom()
            below = anchor.y() > self.rect.bottom()

            onLeft = anchor.x() <= self.rect.left()
            leftOfCenter = anchor.x() > self.rect.left() and anchor.x(
            ) <= self.rect.center().x()
            rightOfCenter = anchor.x() > self.rect.center().x() and anchor.x(
            ) <= self.rect.right()
            onRight = anchor.x() > self.rect.right()

            # get the nearest m_rect corner

            x = (onRight + rightOfCenter) * self.rect.width()
            y = (below + belowCenter) * self.rect.height()
            cornerCase = (above and onLeft) or (above and onRight) or (
                below and onLeft) or (below and onRight)
            vertical = qAbs(anchor.x() - x) > qAbs(anchor.y() - y)

            x1 = x + leftOfCenter * 10 - rightOfCenter * 20 + cornerCase * (
                not vertical) * (onLeft * 10 - onRight * 20)
            y1 = y + aboveCenter * 10 - belowCenter * 20 + cornerCase * vertical * (
                above * 10 - below * 20)

            x2 = x + leftOfCenter * 20 - rightOfCenter * 10 + cornerCase * (
                not vertical) * (onLeft * 20 - onRight * 10)
            y2 = y + aboveCenter * 20 - belowCenter * 10 + cornerCase * vertical * (
                above * 20 - below * 10)

            point1.setX(x1)
            point1.setY(y1)
            point2.setX(x2)
            point2.setY(y2)

            path.moveTo(point1)
            path.lineTo(anchor)
            path.lineTo(point2)

            path = path.simplified()

        painter.setBrush(QColor(255, 255, 255))
        painter.drawPath(path)
        painter.drawText(self.text_rect, self.text)

    def set_anchor(self, point):
        self.anchor = point

    def updateGeometry(self):
        self.prepareGeometryChange()

        self.setPos(self.chart.mapToPosition(self.anchor) + QPoint(10, -50))

    def set_text(self, text):
        self.text = text

        metrics = QFontMetrics(self.font)

        self.text_rect = metrics.boundingRect(QRect(0, 0, 150, 150),
                                              Qt.AlignLeft, self.text)

        self.text_rect.translate(5, 5)

        self.prepareGeometryChange()

        self.rect = QRectF(self.text_rect.adjusted(-5.0, -5.0, 5.0, 5.0))
示例#12
0
class Callout(QGraphicsItem):
    def __init__(self, chart):
        QGraphicsItem.__init__(self, chart)
        self._chart = chart
        self._text = ""
        self._textRect = QRectF()
        self._anchor = QPointF()
        self._font = QFont()
        self._rect = QRectF()

    def boundingRect(self):
        anchor = self.mapFromParent(self._chart.mapToPosition(self._anchor))
        rect = QRectF()
        rect.setLeft(min(self._rect.left(), anchor.x()))
        rect.setRight(max(self._rect.right(), anchor.x()))
        rect.setTop(min(self._rect.top(), anchor.y()))
        rect.setBottom(max(self._rect.bottom(), anchor.y()))

        return rect

    def paint(self, painter, option, widget):
        path = QPainterPath()
        path.addRoundedRect(self._rect, 5, 5)
        anchor = self.mapFromParent(self._chart.mapToPosition(self._anchor))
        if not self._rect.contains(anchor) and not self._anchor.isNull():
            point1 = QPointF()
            point2 = QPointF()

            # establish the position of the anchor point in relation to _rect
            above = anchor.y() <= self._rect.top()
            aboveCenter = (anchor.y() > self._rect.top()
                           and anchor.y() <= self._rect.center().y())
            belowCenter = (anchor.y() > self._rect.center().y()
                           and anchor.y() <= self._rect.bottom())
            below = anchor.y() > self._rect.bottom()

            onLeft = anchor.x() <= self._rect.left()
            leftOfCenter = (anchor.x() > self._rect.left()
                            and anchor.x() <= self._rect.center().x())
            rightOfCenter = (anchor.x() > self._rect.center().x()
                             and anchor.x() <= self._rect.right())
            onRight = anchor.x() > self._rect.right()

            # get the nearest _rect corner.
            x = (onRight + rightOfCenter) * self._rect.width()
            y = (below + belowCenter) * self._rect.height()
            cornerCase = ((above and onLeft) or (above and onRight)
                          or (below and onLeft) or (below and onRight))
            vertical = abs(anchor.x() - x) > abs(anchor.y() - y)

            x1 = (x + leftOfCenter * 10 - rightOfCenter * 20 +
                  cornerCase * int(not vertical) *
                  (onLeft * 10 - onRight * 20))
            y1 = (y + aboveCenter * 10 - belowCenter * 20 +
                  cornerCase * vertical * (above * 10 - below * 20))
            point1.setX(x1)
            point1.setY(y1)

            x2 = (x + leftOfCenter * 20 - rightOfCenter * 10 +
                  cornerCase * int(not vertical) *
                  (onLeft * 20 - onRight * 10))
            y2 = (y + aboveCenter * 20 - belowCenter * 10 +
                  cornerCase * vertical * (above * 20 - below * 10))
            point2.setX(x2)
            point2.setY(y2)

            path.moveTo(point1)
            path.lineTo(anchor)
            path.lineTo(point2)
            path = path.simplified()

        painter.setBrush(QColor(255, 255, 255))
        painter.drawPath(path)
        painter.drawText(self._textRect, self._text)

    def mousePressEvent(self, event):
        event.setAccepted(True)

    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.LeftButton:
            self.setPos(
                mapToParent(event.pos() - event.buttonDownPos(Qt.LeftButton)))
            event.setAccepted(True)
        else:
            event.setAccepted(False)

    def setText(self, text):
        self._text = text
        metrics = QFontMetrics(self._font)
        self._textRect = QRectF(
            metrics.boundingRect(QRect(0.0, 0.0, 150.0, 150.0), Qt.AlignLeft,
                                 self._text))
        self._textRect.translate(5, 5)
        self.prepareGeometryChange()
        self._rect = self._textRect.adjusted(-5, -5, 5, 5)

    def setAnchor(self, point):
        self._anchor = QPointF(point)

    def updateGeometry(self):
        self.prepareGeometryChange()
        self.setPos(self._chart.mapToPosition(self._anchor) + QPointF(10, -50))
示例#13
0
class Room:
    def __init__(self, type='genericRoom', p=QPointF(), w=-1, h=-1):
        self.type = type  # corridor, bedroom, kitchen, bathroom, etc
        self.width = w
        self.height = h
        self.initial_point = p
        self.room_qrect = QRectF()
        self.room_qpolygon = QPolygonF()
        self.area = -1
        self.side = None
        self.door_loc = -1  # 0 entre topL y topR, 1 entre topR y bottomR, 2 entre bottomR y bottomL y 3 entr bL y tL

        self.create_room()

    def create_room(self):
        print(
            f'Creating room of type {self.type} with width = {self.width} and height = {self.height}'
        )
        self.room_qrect = QRectF(self.initial_point.x(),
                                 self.initial_point.y(), self.width,
                                 self.height)
        self.room_qpolygon = QPolygonF(self.room_qrect)
        self.area = abs(self.width * self.height)

    def update_room_dimensions(self):
        self.width = self.room_qrect.width()
        self.height = self.room_qrect.height()
        self.area = abs(self.width * self.height)
        self.room_qpolygon = QPolygonF(self.room_qrect)

    def add_door(self, door_location, room_side):

        self.side = room_side

        dict_location_line = {
            'center':
            QLineF(self.room_qrect.topLeft(), self.room_qrect.topRight()),
            'left':
            QLineF(self.room_qrect.topLeft(), self.room_qrect.bottomLeft()),
            'right':
            QLineF(self.room_qrect.topRight(), self.room_qrect.bottomRight())
        }

        line = dict_location_line[door_location]
        line_lenght = int(line.length())
        step = line_lenght / 100.

        line_points = []
        for t in np.arange(0.25, 0.75, step):
            line_point = line.pointAt(t)
            line_points.append(QPointF(line_point.x(), line_point.y()))

        random_center_door = random.choice(line_points)

        door_sides = {
            'center': {
                'left_door':
                QPointF(random_center_door.x() - 0.5, random_center_door.y()),
                'right_door':
                QPointF(random_center_door.x() + 0.5, random_center_door.y())
            },
            'left': {
                'left_door':
                QPointF(random_center_door.x(),
                        random_center_door.y() - 0.5),
                'right_door':
                QPointF(random_center_door.x(),
                        random_center_door.y() + 0.5)
            },
            'right': {
                'left_door':
                QPointF(random_center_door.x(),
                        random_center_door.y() - 0.5),
                'right_door':
                QPointF(random_center_door.x(),
                        random_center_door.y() + 0.5)
            }
        }

        if door_location == 'center':
            self.room_qpolygon = QPolygonF([
                door_sides[door_location]['right_door'],
                self.room_qrect.topRight(),
                self.room_qrect.bottomRight(),
                self.room_qrect.bottomLeft(),
                self.room_qrect.topLeft(),
                door_sides[door_location]['left_door']
            ])

            self.door_loc = 0

        elif door_location == 'right':

            if room_side == 'bottom':
                self.room_qpolygon = QPolygonF([
                    door_sides[door_location]['right_door'],
                    self.room_qrect.topRight(),
                    self.room_qrect.topLeft(),
                    self.room_qrect.bottomLeft(),
                    self.room_qrect.bottomRight(),
                    door_sides[door_location]['left_door']
                ])

            elif room_side == 'top':
                self.room_qpolygon = QPolygonF([
                    door_sides[door_location]['right_door'],
                    self.room_qrect.bottomRight(),
                    self.room_qrect.bottomLeft(),
                    self.room_qrect.topLeft(),
                    self.room_qrect.topRight(),
                    door_sides[door_location]['left_door']
                ])

            self.door_loc = 1

        elif door_location == 'left':
            if room_side == 'bottom':
                self.room_qpolygon = QPolygonF([
                    door_sides[door_location]['right_door'],
                    self.room_qrect.topLeft(),
                    self.room_qrect.topRight(),
                    self.room_qrect.bottomRight(),
                    self.room_qrect.bottomLeft(),
                    door_sides[door_location]['left_door']
                ])

            elif room_side == 'top':
                self.room_qpolygon = QPolygonF([
                    door_sides[door_location]['right_door'],
                    self.room_qrect.bottomLeft(),
                    self.room_qrect.bottomRight(),
                    self.room_qrect.topRight(),
                    self.room_qrect.topLeft(),
                    door_sides[door_location]['left_door']
                ])

            self.door_loc = 3
示例#14
0
class wheel(QWidget):
    currentColorChanged = Signal(QColor)

    def __init__(self, parent=None):
        super(wheel, self).__init__(parent)
        self.setFixedSize(256, 256)

        # start, end angles for value arc
        self.s_ang, self.e_ang = 135, 225

        # offset angle and direction for color wheel
        self.o_ang, self.rot_d = 45, -1  # 1 for clock-wise, -1 for widdershins

        # other initializations
        self.pos = QPointF(-100, -100)
        self.vIdCen = QPointF(-100, -100)
        self.vIdAng = radians(self.s_ang)
        self.chPt = self.pos
        self.hue = self.sat = self.value = 255

        self.setup()
        self.pos = self.cWhBox.center()

        self._namedColorList = []
        self._namedColorPts = []
        self._showNames = False

        self.setMouseTracking(True)
        self.installEventFilter(self)

        self._startedTimer = False


##    def timerSpinner(self):
##        "won't this be fun"
##        self.o_ang -= 1; self.o_ang %= 360
##        stable = False
##
##        colWhl = QConicalGradient(self.cen, self.o_ang)
##        whl_cols = [Qt.red, Qt.magenta,
##                    Qt.blue, Qt.cyan, Qt.green,
##                    Qt.yellow, Qt.red]
##        for i, c in enumerate(whl_cols[::self.rot_d]):
##            colWhl.setColorAt(i / 6.0, c)
##
##        if stable:  # crosshairs stay on color
##            t = radians(self.hue + self.o_ang * -self.rot_d) * -self.rot_d
##            r = self.sat / 255.0 * self.cW_rad
##            x, y = r * cos(t) + self.cen.x(), r * -sin(t) + self.cen.y()
##            self.chPt = QPointF(x, y)
##        else:  # crosshairs stay on point
##            t = atan2(self.cen.y() - self.pos.y(), self.pos.x() - self.cen.x())
##            h = (int(degrees(t)) - self.o_ang) * -self.rot_d
##            self.hue = (h if h > 0 else h + 360) % 360
##            col = QColor(); col.setHsv(self.hue, self.sat, self.value)
##            self.currentColorChanged.emit(col)
##
##        self.cWhlBrush1 = QBrush(colWhl)
##        self.update()

    def resizeEvent(self, event):
        self.setup()  # re-construct the sizes
        self.setNamedColors(self._namedColorList)

    def getColor(self):
        col = QColor()
        col.setHsv(self.hue, self.sat, self.value)
        return col

    def setNamedColors(self, colorList):
        "sets list [(name, #html)] of named colors"
        self._namedColorList = colorList
        lst = []
        r2 = (self.vAoBox.width() + self.vAiBox.width()) / 4.0
        for i in self._namedColorList:
            h, s, v, a = QColor(i[1]).getHsv()

            t = radians(h + self.o_ang * -self.rot_d) * -self.rot_d
            r = s / 255.0 * self.cW_rad
            x, y = r * cos(t) + self.cen.x(), r * -sin(t) + self.cen.y()
            lst.append(QPointF(x, y))

            #t2 = ((v / 255.0) * self.ang_w + radians(self.e_ang) + 2 * pi) % (2 * pi)
            #x, y = r2 * cos(t2) + self.cen.x(), r2 * -sin(t2) + self.cen.y()
            #lst.append(QPointF(x, y))
        self._namedColorPts = lst

    def showNamedColors(self, flag=False):
        "show/hide location of named colors on color wheel"
        self._showNames = flag
        self.update()

    def setColor(self, color):  # saturation -> radius
        h, s, v, a = color.getHsv()  # hue -> angle
        self.hue, self.sat, self.value = h, s, v  # value -> side bar thingy

        t = radians(h + self.o_ang * -self.rot_d) * -self.rot_d
        r = s / 255.0 * self.cW_rad
        x, y = r * cos(t) + self.cen.x(), r * -sin(t) + self.cen.y()
        self.chPt = QPointF(x, y)  # hue, saturation

        self.vIdAng = t2 = (v / 255.0) * self.ang_w + radians(self.e_ang)
        self.vIdAng = t2 = t2 if t2 > 0 else t2 + 2 * pi
        r2 = self.vAoBox.width() / 2.0

        x, y = r2 * cos(t2) + self.cen.x(), r2 * -sin(t2) + self.cen.y()
        self.vIdCen, self.vIdAng = QPointF(x, y), t2  # value
        self.vIdBox.moveCenter(self.vIdCen)
        self.update()

    def eventFilter(self, source, event):
        if (event.type() == QEvent.MouseButtonPress
                or (event.type() == QEvent.MouseMove
                    and event.buttons() == Qt.LeftButton)):
            self.pos = pos = event.pos()

            t = atan2(self.cen.y() - pos.y(), pos.x() - self.cen.x())
            if self.colWhlPath.contains(pos):  # in the color wheel
                self.chPt = pos

                #if not self._startedTimer:
                #    self.timer = QTimer()
                #    self.timer.timeout.connect(self.timerSpinner)
                #    self.timer.start(30.303)
                #    self._startedTimer = True

                # hue -> mouse angle (same as t here)
                h = (int(degrees(t)) - self.o_ang) * -self.rot_d
                self.hue = (h if h > 0 else h + 360) % 360

                # saturation -> mouse radius (clipped to wheel radius)
                m_rad = sqrt((self.pos.x() - self.cen.x())**2 +
                             (self.pos.y() - self.cen.y())**2)
                self.sat = int(255 * min(m_rad / self.cW_rad, 1))

            if self.vInArcPath.contains(pos):  # in the value selection arc
                self.vIdAng = t if t > 0 else t + 2 * pi
                r2 = self.vAoBox.width() / 2.0

                x, y = r2 * cos(t) + self.cen.x(), r2 * -sin(t) + self.cen.y()
                self.vIdCen = QPointF(x, y)
                self.vIdBox.moveCenter(self.vIdCen)
                self.value = int(255 *
                                 (t - radians(self.e_ang)) / self.ang_w) % 256

            self.update()
            col = QColor()
            col.setHsv(self.hue, self.sat, self.value)
            self.currentColorChanged.emit(col)
        return QWidget.eventFilter(self, source, event)

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(painter.Antialiasing)

        #painter.setBrush(QBrush(Qt.black, Qt.NoBrush))
        #painter.drawRect(self.winBox)  # border

        # value selector indicator
        painter.setBrush(QBrush(Qt.black, Qt.SolidPattern))
        painter.drawPie(self.vIdBox, 16 * (degrees(self.vIdAng) - 22.5), 720)

        # value selector arc
        painter.setClipPath(self.vArcPath)
        painter.setPen(Qt.NoPen)
        arc = QConicalGradient(self.cen, self.e_ang)
        color = QColor()
        color.setHsv(self.hue, self.sat, 255)
        arc.setColorAt(1 - (self.e_ang - self.s_ang) / 360.0, color)
        arc.setColorAt(1, Qt.black)
        arc.setColorAt(0, Qt.black)
        painter.setBrush(arc)
        painter.drawPath(self.vArcPath)
        painter.setClipPath(self.vArcPath, Qt.NoClip)

        # color wheel
        painter.setPen(Qt.NoPen)
        painter.setBrush(self.cWhlBrush1)
        painter.drawEllipse(self.cWhBox)
        painter.setBrush(self.cWhlBrush2)
        painter.drawEllipse(self.cWhBox)

        # crosshairs
        painter.setClipPath(self.colWhlPath)
        painter.setBrush(QBrush(Qt.black, Qt.SolidPattern))
        chVert = QRectF(0, 0, 2, 20)
        chHort = QRectF(0, 0, 20, 2)
        chVert.moveCenter(self.chPt)
        chHort.moveCenter(self.chPt)
        painter.drawRect(chVert)
        painter.drawRect(chHort)

        # named color locations
        if self._showNames:
            painter.setClipPath(self.vArcPath, Qt.NoClip)
            painter.setPen(Qt.SolidLine)
            try:
                painter.drawPoints(*self._namedColorPts)  # PyQt
            except:
                painter.drawPoints(self._namedColorPts)  # PySide

    def setup(self):
        "sets bounds on value arc and color wheel"
        # bounding boxes
        self.winBox = QRectF(self.rect())
        self.vIoBox = QRectF()  # value indicator arc outer
        self.vIdBox = QRectF()  # value indicator box
        self.vAoBox = QRectF()  # value arc outer
        self.vAiBox = QRectF()  # value arc inner
        self.cWhBox = QRectF()  # color wheel

        self.vIdBox.setSize(QSizeF(15, 15))
        self.vIoBox.setSize(self.winBox.size())
        self.vAoBox.setSize(self.winBox.size() - self.vIdBox.size() / 2.0)
        self.vAiBox.setSize(self.vAoBox.size() - QSizeF(20, 20))
        self.cWhBox.setSize(self.vAiBox.size() - QSizeF(20, 20))

        # center - shifted to the right slightly
        x = self.winBox.width() - (self.vIdBox.width() +
                                   self.vAiBox.width()) / 2.0
        self.cen = QPointF(x, self.winBox.height() / 2.0)

        # positions and initial settings
        self.vAoBox.moveCenter(self.cen)
        self.vAiBox.moveCenter(self.cen)
        self.cWhBox.moveCenter(self.cen)
        self.vIdBox.moveCenter(self.vIdCen)

        self.cW_rad = self.cWhBox.width() / 2.0
        self.ang_w = radians(self.s_ang) - radians(self.e_ang)

        # gradients
        colWhl = QConicalGradient(self.cen, self.o_ang)
        whl_cols = [
            Qt.red, Qt.magenta, Qt.blue, Qt.cyan, Qt.green, Qt.yellow, Qt.red
        ]
        for i, c in enumerate(whl_cols[::self.rot_d]):
            colWhl.setColorAt(i / 6.0, c)

        rad = min(self.cWhBox.width() / 2.0, self.cWhBox.height() / 2.0)
        cWhlFade = QRadialGradient(self.cen, rad, self.cen)
        cWhlFade.setColorAt(0, Qt.white)
        cWhlFade.setColorAt(1, QColor(255, 255, 255, 0))

        self.cWhlBrush1 = QBrush(colWhl)
        self.cWhlBrush2 = QBrush(cWhlFade)

        # painter paths (arcs, wheel)
        rad = self.vAoBox.width() / 2.0
        x, y = rad * cos(radians(self.s_ang)), -rad * sin(radians(self.s_ang))
        x += self.cen.x()
        y += self.cen.y()

        self.vArcPath = QPainterPath(QPointF(x, y))  # value arc (for color)
        self.vArcPath.arcTo(self.vAoBox, self.s_ang, self.e_ang - self.s_ang)
        self.vArcPath.arcTo(self.vAiBox, self.e_ang, self.s_ang - self.e_ang)
        self.vArcPath.closeSubpath()

        self.vInArcPath = QPainterPath(QPointF(x, y))  # value arc (for mouse)
        self.vInArcPath.arcTo(self.vIoBox, self.s_ang, self.e_ang - self.s_ang)
        self.vInArcPath.arcTo(self.vAiBox, self.e_ang, self.s_ang - self.e_ang)
        self.vInArcPath.closeSubpath()

        self.colWhlPath = QPainterPath()
        self.colWhlPath.addEllipse(self.cWhBox)
示例#15
0
    def redraw(self):
        self.graphics_scene.clear()

        # draw screenshot
        self.graphics_scene.addPixmap(self.screenPixel)

        # prepare for drawing selected area
        rect = QRectF(self.selected_area)
        rect = rect.normalized()

        top_left_point = rect.topLeft()
        top_right_point = rect.topRight()
        bottom_left_point = rect.bottomLeft()
        bottom_right_point = rect.bottomRight()
        top_middle_point = (top_left_point + top_right_point) / 2
        left_middle_point = (top_left_point + bottom_left_point) / 2
        bottom_middle_point = (bottom_left_point + bottom_right_point) / 2
        right_middle_point = (top_right_point + bottom_right_point) / 2

        # draw the picture mask
        mask = QColor(0, 0, 0, 155)

        if self.selected_area == QRect():
            self.graphics_scene.addRect(0, 0, self.screenPixel.width(),
                                        self.screenPixel.height(),
                                        QPen(Qt.NoPen), mask)
        else:
            self.graphics_scene.addRect(0, 0, self.screenPixel.width(),
                                        top_right_point.y(), QPen(Qt.NoPen),
                                        mask)
            self.graphics_scene.addRect(0, top_left_point.y(),
                                        top_left_point.x(), rect.height(),
                                        QPen(Qt.NoPen), mask)
            self.graphics_scene.addRect(
                top_right_point.x(), top_right_point.y(),
                self.screenPixel.width() - top_right_point.x(), rect.height(),
                QPen(Qt.NoPen), mask)
            self.graphics_scene.addRect(
                0, bottom_left_point.y(), self.screenPixel.width(),
                self.screenPixel.height() - bottom_left_point.y(),
                QPen(Qt.NoPen), mask)

        # draw the toolBar
        if self.action != ACTION_SELECT:
            spacing = 5
            # show the toolbar first, then move it to the correct position
            # because the width of it may be wrong if this is the first time it shows
            self.tooBar.show()

            dest = QPointF(rect.bottomRight() -
                           QPointF(self.tooBar.width(), 0) -
                           QPointF(spacing, -spacing))
            if dest.x() < spacing:
                dest.setX(spacing)
            pen_set_bar_height = self.penSetBar.height(
            ) if self.penSetBar is not None else 0
            if dest.y() + self.tooBar.height(
            ) + pen_set_bar_height >= self.height():
                if rect.top() - self.tooBar.height(
                ) - pen_set_bar_height < spacing:
                    dest.setY(rect.top() + spacing)
                else:
                    dest.setY(rect.top() - self.tooBar.height() -
                              pen_set_bar_height - spacing)

            self.tooBar.move(dest.toPoint())

            if self.penSetBar is not None:
                self.penSetBar.show()
                self.penSetBar.move(dest.toPoint() +
                                    QPoint(0,
                                           self.tooBar.height() + spacing))

                if self.action == ACTION_TEXT:
                    self.penSetBar.showFontWidget()
                else:
                    self.penSetBar.showPenWidget()
        else:
            self.tooBar.hide()

            if self.penSetBar is not None:
                self.penSetBar.hide()

        # draw the list
        for step in self.drawListResult:
            self.drawOneStep(step)

        if self.drawListProcess is not None:
            self.drawOneStep(self.drawListProcess)
            if self.action != ACTION_TEXT:
                self.drawListProcess = None

        if self.selected_area != QRect():
            self.items_to_remove = []

            # draw the selected rectangle
            pen = QPen(QColor(0, 255, 255), 2)
            self.items_to_remove.append(self.graphics_scene.addRect(rect, pen))

            # draw the drag point
            radius = QPoint(3, 3)
            brush = QBrush(QColor(0, 255, 255))
            self.items_to_remove.append(
                self.graphics_scene.addEllipse(
                    QRectF(top_left_point - radius, top_left_point + radius),
                    pen, brush))
            self.items_to_remove.append(
                self.graphics_scene.addEllipse(
                    QRectF(top_middle_point - radius,
                           top_middle_point + radius), pen, brush))
            self.items_to_remove.append(
                self.graphics_scene.addEllipse(
                    QRectF(top_right_point - radius, top_right_point + radius),
                    pen, brush))
            self.items_to_remove.append(
                self.graphics_scene.addEllipse(
                    QRectF(left_middle_point - radius,
                           left_middle_point + radius), pen, brush))
            self.items_to_remove.append(
                self.graphics_scene.addEllipse(
                    QRectF(right_middle_point - radius,
                           right_middle_point + radius), pen, brush))
            self.items_to_remove.append(
                self.graphics_scene.addEllipse(
                    QRectF(bottom_left_point - radius,
                           bottom_left_point + radius), pen, brush))
            self.items_to_remove.append(
                self.graphics_scene.addEllipse(
                    QRectF(bottom_middle_point - radius,
                           bottom_middle_point + radius), pen, brush))
            self.items_to_remove.append(
                self.graphics_scene.addEllipse(
                    QRectF(bottom_right_point - radius,
                           bottom_right_point + radius), pen, brush))

        # draw the textedit
        if self.textPosition is not None:
            textSpacing = 50
            position = QPoint()
            if self.textPosition.x() + self.textInput.width(
            ) >= self.screenPixel.width():
                position.setX(self.textPosition.x() - self.textInput.width())
            else:
                position.setX(self.textPosition.x())

            if self.textRect is not None:
                if self.textPosition.y() + self.textInput.height(
                ) + self.textRect.height() >= self.screenPixel.height():
                    position.setY(self.textPosition.y() -
                                  self.textInput.height() -
                                  self.textRect.height())
                else:
                    position.setY(self.textPosition.y() +
                                  self.textRect.height())
            else:
                if self.textPosition.y() + self.textInput.height(
                ) >= self.screenPixel.height():
                    position.setY(self.textPosition.y() -
                                  self.textInput.height())
                else:
                    position.setY(self.textPosition.y())

            self.textInput.move(position)
            self.textInput.show()
            # self.textInput.getFocus()

        # draw the magnifier
        if self.action == ACTION_SELECT:
            self.drawMagnifier()
            if self.mousePressed:
                self.drawSizeInfo()

        if self.action == ACTION_MOVE_SELECTED:
            self.drawSizeInfo()
示例#16
0
class Apartment:
    def __init__(self, coppelia_, n_rooms):

        self.coppelia = coppelia_

        self.num_rooms = n_rooms
        self.max_rooms_per_side = math.ceil(self.num_rooms / 2)

        self.initial_corridor_width = -1
        self.initial_corridor_height = -1

        self.initial_corridor = QRectF()

        self.fixed_height = random.uniform(4, 6)

        # Almacena los indices de las habitaciones que tendrán a su izquierda un pasillo
        self.dict_corridors_index_per_side = {'bottom': [], 'top': []}
        self.dict_rooms_per_side = {'bottom': [], 'top': []}
        self.dict_rooms_and_corridors_per_side = {'bottom': [], 'top': []}

        # Lista final una vez hechas todas las transformaciones
        self.total_rooms_and_corridors = []

        self.create_initial_corridor()
        self.select_side_corridors()

        self.get_random_rooms()
        self.adjust_rooms()  # to avoid narrow corridors

        self.add_doors()
        self.center_apartment()
        self.add_floor_per_room()
        self.add_walls()

    def create_initial_corridor(self):
        self.initial_corridor_height = random.uniform(1.5, 3)
        self.initial_corridor_width = random.uniform(self.num_rooms * 4 / 2,
                                                     self.num_rooms * 8 / 2)

        self.initial_corridor = QRectF(
            0, 0, self.initial_corridor_width, -self.initial_corridor_height
        )  # - height para que la parte de arriba sea el top
        self.initial_corridor.translate(-self.initial_corridor.center())

    def select_side_corridors(self):
        # -1 sin pasillo, 0 antes de la primera habitacion, 1 antes de la segunda
        corridor_position = np.arange(-1, self.max_rooms_per_side)

        possibles_corridors_per_side = round(self.max_rooms_per_side / 2)

        if possibles_corridors_per_side == 0:
            possibles_corridors_per_side = 1

        self.dict_corridors_index_per_side['top'] = random.sample(
            list(corridor_position), k=possibles_corridors_per_side)
        self.dict_corridors_index_per_side['bottom'] = random.sample(
            list(corridor_position), k=possibles_corridors_per_side)

        while -1 in self.dict_corridors_index_per_side['top']:
            self.dict_corridors_index_per_side['top'].remove(-1)

        while -1 in self.dict_corridors_index_per_side['bottom']:
            self.dict_corridors_index_per_side['bottom'].remove(-1)

        print('posicion pasillo parte superior',
              self.dict_corridors_index_per_side['top'])
        print('posicion pasillo parte inferior',
              self.dict_corridors_index_per_side['bottom'])

    def get_random_rooms(self):

        dict_opposite_side = {'bottom': 'top', 'top': 'bottom'}

        for i in range(0, self.num_rooms):

            random_side = random.choice(['top', 'bottom'])

            if len(self.dict_rooms_per_side[random_side]
                   ) >= self.max_rooms_per_side:
                random_side = dict_opposite_side[random_side]

            # El indice de mi habitacion está en la lista de pasillos por indice luego tengo que añadir un pasillo a
            # su izquierda
            if len(self.dict_rooms_per_side[random_side]
                   ) in self.dict_corridors_index_per_side[random_side]:
                self.add_corridor(random_side, self.initial_corridor_height,
                                  self.fixed_height)

            if len(self.dict_rooms_and_corridors_per_side[random_side]) == 0:

                if random_side == 'bottom':
                    initial_point = self.initial_corridor.bottomLeft()
                else:
                    initial_point = self.initial_corridor.topLeft() + QPointF(
                        0, self.fixed_height)

            else:
                initial_point = self.dict_rooms_and_corridors_per_side[
                    random_side][-1].room_qrect.topRight()

            room = Room(type='genericRoom',
                        p=initial_point,
                        w=random.uniform(4, 8),
                        h=-self.fixed_height)

            self.dict_rooms_and_corridors_per_side[random_side].append(room)
            self.dict_rooms_per_side[random_side].append(room)

        for room_location in ['top', 'bottom']:
            if len(self.dict_rooms_per_side[room_location]
                   ) in self.dict_corridors_index_per_side[room_location]:
                try:
                    if self.dict_rooms_and_corridors_per_side[room_location][
                            -1].type != 'corridor':
                        self.add_corridor(random_side,
                                          self.initial_corridor_height,
                                          self.fixed_height)
                except:
                    print('there isnt rooms in this side of the corridor')

    def add_corridor(self, side, corridor_width, corridor_height):

        if len(self.dict_rooms_and_corridors_per_side[side]) == 0:

            if side == 'bottom':
                initial_point = self.initial_corridor.bottomLeft()
            else:
                initial_point = self.initial_corridor.topLeft() + QPointF(
                    0, self.fixed_height)

        else:
            initial_point = self.dict_rooms_and_corridors_per_side[side][
                -1].room_qrect.topRight()

        corridor = Room(type='corridor',
                        p=initial_point,
                        w=corridor_width,
                        h=-corridor_height)

        self.dict_rooms_and_corridors_per_side[side].append(corridor)

    def adjust_rooms(self):

        if self.num_rooms == 1:
            return

        dict_side_width = {'bottom': 0., 'right': 0., 'top': 0., 'left': 0.}

        for side, rooms in self.dict_rooms_per_side.items():
            print(f' side {side} has {len(rooms)} rooms ')
            for room in rooms:
                r = room.room_qrect
                dict_side_width[side] += r.width()

        diff = abs(dict_side_width['top'] - dict_side_width['bottom'])

        dict_opposite_side = {
            'bottom': 'top',
            'right': 'left',
            'top': 'bottom',
            'left': 'right'
        }

        if dict_side_width['top'] > dict_side_width['bottom']:
            print('top side is longer')
            side_to_modify = 'bottom'
        else:
            print('bottom side is longer')
            side_to_modify = 'top'

        print(f'--- Modifying {side_to_modify} room ---')

        room_to_modify = self.dict_rooms_and_corridors_per_side[
            side_to_modify][-1]
        opposite_room = self.dict_rooms_and_corridors_per_side[
            dict_opposite_side[side_to_modify]][-1]

        my_side_right = room_to_modify.room_qrect.topRight()
        opposite_side_right = opposite_room.room_qrect.topRight()

        if room_to_modify.type == 'corridor':
            print(f' Room of type {room_to_modify.type} ')

            room_to_modify.room_qrect.setTopRight(
                QPointF(opposite_side_right.x(), my_side_right.y()))

            self.dict_rooms_and_corridors_per_side[side_to_modify][
                -1] = room_to_modify
            self.dict_rooms_and_corridors_per_side[side_to_modify][
                -1].update_room_dimensions()

        else:
            if diff < self.initial_corridor_height:
                print('widening room')
                num_corridors_to_add = 0
            else:
                print('widening room and creating corridor')
                num_corridors_to_add = 1

            print(
                f' Room of type {room_to_modify.type}  -- adding {num_corridors_to_add} corridors'
            )

            room_to_modify.room_qrect.setTopRight(
                QPointF(
                    opposite_side_right.x() -
                    num_corridors_to_add * self.initial_corridor_height,
                    my_side_right.y()))
            self.dict_rooms_and_corridors_per_side[side_to_modify][
                -1] = room_to_modify
            self.dict_rooms_and_corridors_per_side[side_to_modify][
                -1].update_room_dimensions()

            if num_corridors_to_add > 0:
                self.add_corridor(side=side_to_modify,
                                  corridor_width=num_corridors_to_add *
                                  self.initial_corridor_height,
                                  corridor_height=self.fixed_height)

    def add_doors(self):
        opposite = {'bottom': 'top', 'top': 'bottom'}

        for current_side, rooms in self.dict_rooms_per_side.items():

            for i, room in enumerate(rooms):

                possibles_door_locations = [opposite[current_side]]

                if i in self.dict_corridors_index_per_side[
                        current_side]:  # Pasillo a la izquierda
                    possibles_door_locations.append('left')

                if i + 1 in self.dict_corridors_index_per_side[current_side]:
                    possibles_door_locations.append('right')

                door_location = random.choice(possibles_door_locations)
                room.add_door(door_location)

    def center_apartment(self):
        union_polygon = QPolygonF()

        for list in self.dict_rooms_and_corridors_per_side.values():
            for room in list:
                union_polygon = union_polygon.united(
                    room.room_qpolygon)  # Para obtener el bounding box
                self.total_rooms_and_corridors.append(room)

        self.initial_corridor.setLeft(union_polygon.boundingRect().left())
        self.initial_corridor.setRight(union_polygon.boundingRect().right())

        self.total_rooms_and_corridors.append(
            Room(type='corridor',
                 p=self.initial_corridor.topLeft(),
                 w=self.initial_corridor.width(),
                 h=self.initial_corridor.height()))

        union_polygon = union_polygon.united(self.initial_corridor)

        initial_center = union_polygon.boundingRect().center()
        union_polygon.translate(-initial_center)

        self.apartment_boundingRect = union_polygon.boundingRect()

        # Desplazo habitaciones y pasillos al centro
        for i, room in enumerate(self.total_rooms_and_corridors):
            room.room_qpolygon.translate(
                -initial_center
            )  # Desplazo los poligonos para que la habitación esté centrada
            room.room_qrect.translate(-initial_center)

    def add_walls(self):

        for i, room in enumerate(self.total_rooms_and_corridors):
            walls = []
            if room.type == 'corridor':
                continue

            polygon = room.room_qpolygon

            prev_point = polygon[0]
            for i, curr_point in enumerate(polygon):
                if i == 0:
                    continue
                walls.append(([prev_point.x(),
                               prev_point.y(),
                               .425], [curr_point.x(),
                                       curr_point.y(), .425]))
                prev_point = curr_point

            room.walls = walls

            wall_thread = WallCreator(data, walls)
            wall_thread.start()

        walls = []

        polygon_br = QPolygonF(self.apartment_boundingRect, closed=True)
        prev_point_br = polygon_br[0]
        for i, curr_point_br in enumerate(polygon_br):
            if i == 0:
                continue

            walls.append(([prev_point_br.x(),
                           prev_point_br.y(),
                           .4], [curr_point_br.x(),
                                 curr_point_br.y(), .4]))
            prev_point_br = curr_point_br

        wall_thread = WallCreator(data, walls)
        wall_thread.start()

    def add_floor(self):  # un suelo conjunto para el apartamento

        fscale_x = self.apartment_boundingRect.width() / 5 + 0.5
        fscale_y = self.apartment_boundingRect.height() / 5 + 0.5

        # Create and scale a floor
        r = self.coppelia.create_model(
            'models/infrastructure/floors/5mX5m wooden floor.ttm', 0, 0, 0, 0)

        self.coppelia.scale_object(r, fscale_x, fscale_y, 1)
        for handle in self.coppelia.get_objects_children(r):
            self.coppelia.scale_object(handle, fscale_x, fscale_y, 1)

    def add_floor_per_room(self):

        for room in self.total_rooms_and_corridors:

            room_boundingRect = room.room_qpolygon.boundingRect()
            room_center = room_boundingRect.center()

            fscale_x = room_boundingRect.width() / 5
            fscale_y = room_boundingRect.height() / 5

            if room.type == 'corridor':
                floor = self.coppelia.create_model(
                    'models/infrastructure/floors/5mX5m wooden floor.ttm',
                    room_center.x(), room_center.y(), 0, 0)
            else:
                floor = self.coppelia.create_model(
                    'models/infrastructure/floors/5mX5m concrete floor.ttm',
                    room_center.x(), room_center.y(), 0, 0)

            self.coppelia.scale_object(floor, fscale_x, fscale_y, 1)
示例#17
0
class Callout(QGraphicsItem):

    def __init__(self, chart):
        QGraphicsItem.__init__(self, chart)
        self._chart = chart
        self._text = ""
        self._textRect = QRectF()
        self._anchor = QPointF()
        self._font = QFont()
        self._rect = QRectF()

    def boundingRect(self):
        anchor = self.mapFromParent(self._chart.mapToPosition(self._anchor))
        rect = QRectF()
        rect.setLeft(min(self._rect.left(), anchor.x()))
        rect.setRight(max(self._rect.right(), anchor.x()))
        rect.setTop(min(self._rect.top(), anchor.y()))
        rect.setBottom(max(self._rect.bottom(), anchor.y()))

        return rect

    def paint(self, painter, option, widget):
        path = QPainterPath()
        path.addRoundedRect(self._rect, 5, 5)
        anchor = self.mapFromParent(self._chart.mapToPosition(self._anchor))
        if not self._rect.contains(anchor) and not self._anchor.isNull():
            point1 = QPointF()
            point2 = QPointF()

            # establish the position of the anchor point in relation to _rect
            above = anchor.y() <= self._rect.top()
            aboveCenter = (anchor.y() > self._rect.top() and
                anchor.y() <= self._rect.center().y())
            belowCenter = (anchor.y() > self._rect.center().y() and
                anchor.y() <= self._rect.bottom())
            below = anchor.y() > self._rect.bottom()

            onLeft = anchor.x() <= self._rect.left()
            leftOfCenter = (anchor.x() > self._rect.left() and
                anchor.x() <= self._rect.center().x())
            rightOfCenter = (anchor.x() > self._rect.center().x() and
                anchor.x() <= self._rect.right())
            onRight = anchor.x() > self._rect.right()

            # get the nearest _rect corner.
            x = (onRight + rightOfCenter) * self._rect.width()
            y = (below + belowCenter) * self._rect.height()
            cornerCase = ((above and onLeft) or (above and onRight) or
                (below and onLeft) or (below and onRight))
            vertical = abs(anchor.x() - x) > abs(anchor.y() - y)

            x1 = (x + leftOfCenter * 10 - rightOfCenter * 20 + cornerCase *
                int(not vertical) * (onLeft * 10 - onRight * 20))
            y1 = (y + aboveCenter * 10 - belowCenter * 20 + cornerCase *
                vertical * (above * 10 - below * 20))
            point1.setX(x1)
            point1.setY(y1)

            x2 = (x + leftOfCenter * 20 - rightOfCenter * 10 + cornerCase *
                int(not vertical) * (onLeft * 20 - onRight * 10))
            y2 = (y + aboveCenter * 20 - belowCenter * 10 + cornerCase *
                vertical * (above * 20 - below * 10))
            point2.setX(x2)
            point2.setY(y2)

            path.moveTo(point1)
            path.lineTo(anchor)
            path.lineTo(point2)
            path = path.simplified()

        painter.setBrush(QColor(255, 255, 255))
        painter.drawPath(path)
        painter.drawText(self._textRect, self._text)

    def mousePressEvent(self, event):
        event.setAccepted(True)

    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.LeftButton:
            self.setPos(mapToParent(
                event.pos() - event.buttonDownPos(Qt.LeftButton)))
            event.setAccepted(True)
        else:
            event.setAccepted(False)

    def setText(self, text):
        self._text = text
        metrics = QFontMetrics(self._font)
        self._textRect = QRectF(metrics.boundingRect(
            QRect(0.0, 0.0, 150.0, 150.0),Qt.AlignLeft, self._text))
        self._textRect.translate(5, 5)
        self.prepareGeometryChange()
        self._rect = self._textRect.adjusted(-5, -5, 5, 5)

    def setAnchor(self, point):
        self._anchor = QPointF(point)

    def updateGeometry(self):
        self.prepareGeometryChange()
        self.setPos(self._chart.mapToPosition(
            self._anchor) + QPointF(10, -50))
示例#18
0
class Room:
    def __init__(self, type='genericRoom', p=QPointF(), w=-1, h=-1):
        self.type = type  # corridor, bedroom, kitchen, bathroom, etc
        self.width = w
        self.height = h
        self.initial_point = p
        self.room_qrect = QRectF()
        self.room_qpolygon = QPolygonF()
        self.area = -1
        self.door_position = None
        self.create_room()

    def create_room(self):
        print(
            f'Creating room of type {self.type} with width = {self.width} and height = {self.height}'
        )
        self.room_qrect = QRectF(self.initial_point.x(),
                                 self.initial_point.y(), self.width,
                                 self.height)
        self.room_qpolygon = QPolygonF(self.room_qrect)
        self.area = abs(self.width * self.height)

    def update_room_dimensions(self):
        self.width = self.room_qrect.width()
        self.height = self.room_qrect.height()
        self.area = abs(self.width * self.height)
        self.room_qpolygon = QPolygonF(self.room_qrect)

    def add_door(self, door_location):
        self.door_position = door_location

        # Diferenciar entre parte de arriba y parte de abajo
        dict_location_line = {
            'top':
            QLineF(self.room_qrect.topLeft(), self.room_qrect.topRight()),
            'bottom':
            QLineF(self.room_qrect.bottomLeft(),
                   self.room_qrect.bottomRight()),
            'left':
            QLineF(self.room_qrect.topLeft(), self.room_qrect.bottomLeft()),
            'right':
            QLineF(self.room_qrect.topRight(), self.room_qrect.bottomRight())
        }

        line = dict_location_line[door_location]
        line_lenght = int(line.length())
        step = line_lenght / 100.

        line_points = []
        for t in np.arange(0.25, 0.75, step):
            line_point = line.pointAt(t)
            line_points.append(QPointF(line_point.x(), line_point.y()))

        door = random.choice(line_points)

        room_polygon = {
            'top':
            QPolygonF([
                QPointF(door.x() + 0.5, door.y()),
                self.room_qrect.topRight(),
                self.room_qrect.bottomRight(),
                self.room_qrect.bottomLeft(),
                self.room_qrect.topLeft(),
                QPointF(door.x() - 0.5, door.y())
            ]),
            'bottom':
            QPolygonF([
                QPointF(door.x() + 0.5, door.y()),
                self.room_qrect.bottomRight(),
                self.room_qrect.topRight(),
                self.room_qrect.topLeft(),
                self.room_qrect.bottomLeft(),
                QPointF(door.x() - 0.5, door.y())
            ]),
            'right':
            QPolygonF([
                QPointF(door.x(),
                        door.y() + 0.5),
                self.room_qrect.topRight(),
                self.room_qrect.topLeft(),
                self.room_qrect.bottomLeft(),
                self.room_qrect.bottomRight(),
                QPointF(door.x(),
                        door.y() - 0.5)
            ]),
            'left':
            QPolygonF([
                QPointF(door.x(),
                        door.y() + 0.5),
                self.room_qrect.topLeft(),
                self.room_qrect.topRight(),
                self.room_qrect.bottomRight(),
                self.room_qrect.bottomLeft(),
                QPointF(door.x(),
                        door.y() - 0.5)
            ])
        }

        self.room_qpolygon = room_polygon[door_location]
示例#19
0
class NavBar(QWidget):
    """
    滑动导航条控件
    作者:feiyangqingyun(QQ:517216493) 2016-10-8
    译者:sunchuquin(QQ:1715216365) 2020-12-15
    1. 可键盘按键上下移动元素功能
    2. 支持窗体大小改变控件自动拉伸
    3. 支持移动到第一个/末一个/上移/下移/移动到指定索引/移动到指定元素
    4. 支持扁平处理
    5. 支持纵向风格
    6. 可设置圆角角度,包括主背景和选中元素背景
    7. 可设置间距
    8. 可设置导航条主背景渐变色
    9. 可设置当前条目选中背景渐变色
    10. 可设置条目未选中和选中的文字颜色
    11. 可设置五种选中风格样式
    12. 可设置线条颜色和宽度
    13. 选中条目的宽度为条目文字集合中最长的一个
    """

    # 当前条目改变信号
    currentItemChanged: Signal = Signal(int, str)  # int: 当前条目的索引, str: 当前条目的文字

    @QEnum
    class BarStyle(Enum):
        BARSTYLE_RECT = 0  # 圆角矩形
        BARSTYLE_LINE_TOP = 1  # 顶部线条
        BARSTYLE_LINE_RIGHT = 2  # 右侧线条
        BARSTYLE_LINE_BOTTOM = 3  # 底部线条
        BARSTYLE_LINE_LEFT = 4  # 左侧线条

    def __init__(self, parent=None):
        super(NavBar, self).__init__(parent)

        self.__bgColorStart: QColor = QColor(121, 121, 121)  # 导航条主背景渐变开始颜色
        self.__bgColorEnd: QColor = QColor(78, 78, 78)  # 导航条主背景渐变结束颜色
        self.__old_bgColorEnd: QColor = self.__bgColorEnd  # 用于扁平化切换

        self.__barColorStart: QColor = QColor(46, 132, 243)  # 导航条当前条目渐变开始颜色
        self.__barColorEnd: QColor = QColor(39, 110, 203)  # 导航条当前条目渐变结束颜色
        self.__old_barColorEnd: QColor = self.__barColorEnd  # 用于扁平化切换

        self.__textNormalColor: QColor = QColor(230, 230, 230)  # 文字正常颜色
        self.__textSelectColor: QColor = QColor(255, 255, 255)  # 文字选中颜色

        self.__items: str = ""  # 所有条目文字信息
        self.__currentIndex: int = -1  # 当前选中条目索引
        self.__currentItem: str = ""  # 当前选中条目文字

        self.__bgRadius: int = 0  # 背景圆角半径
        self.__barRadius: int = 0  # 选中条目背景圆角半径
        self.__space: int = 25  # 条目元素之间的间距

        self.__lineWidth: int = 3  # 线条宽度
        self.__lineColor: QColor = QColor(255, 107, 107)  # 线条颜色

        self.__barStyle: NavBar.BarStyle = NavBar.BarStyle.BARSTYLE_RECT  # 选中元素样式

        self.__keyMove: bool = True  # 是否支持按键移动
        self.__horizontal: bool = False  # 是否横向显示
        self.__flat: bool = False  # 是否扁平化

        self.__listItem: list = []  # 元素集合,成对出现,元素的名字,矩形区域范围

        self.__barRect: QRectF = QRectF()  # 选中区域的矩形
        self.__targetRect: QRectF = QRectF()  # 目标区域的矩形
        self.__barLen: Decimal = Decimal(0)  # 选中区域的长度
        self.__targetLen: Decimal = Decimal(0)  # 目标区域的长度

        self.__initLen: Decimal = Decimal(10)  # 导航条的长度
        self.__step: int = 0  # 每次移动的步长

        self.__isForward: bool = True  # 是否往前移动
        self.__isVirgin: bool = True  # 是否首次处理
        self.__timer: QTimer = QTimer(self)  # 滑动绘制定时器
        self.__timer.setInterval(10)
        self.__timer.timeout.connect(self.__slide)

        self.setItems("主界面|系统设置|防区管理|警情查询|视频预览")

    @staticmethod
    def __initStep(distance: int) -> int:
        """ 计算步长 """
        n: int = 1
        while True:
            if (n * n) > distance:
                break
            else:
                n += 1

        return int(n * 1.4)

    def resizeEvent(self, event: QResizeEvent) -> None:
        """ 控件大小调整事件 """
        index: int = 0
        count: int = len(self.__listItem)
        if count == 0:
            return

        if (count > 0) and (not self.__currentItem):
            # 相当于初始化,只会执行一次
            self.__currentIndex = 0
            self.__currentItem = self.__listItem[0][0]

        for i in range(count):
            if self.__listItem[i][0] == self.__currentItem:
                index = i
                break

        self.moveTo_int(index)

    def mousePressEvent(self, event: QMouseEvent) -> None:
        """ 鼠标按压信号 """
        self.moveTo_point(event.pos())

    def keyPressEvent(self, event: QKeyEvent) -> None:
        """  """
        if not self.__keyMove:
            return

        if (event.key() == Qt.Key_Left) or (event.key() == Qt.Key_Up):
            self.movePrevious()
        elif (event.key() == Qt.Key_Right) or (event.key() == Qt.Key_Down):
            self.moveNext()

    def paintEvent(self, event: QPaintEvent) -> None:
        """  """
        # 绘制准备工作,启用反锯齿
        painter: QPainter = QPainter(self)
        painter.setRenderHints(QPainter.Antialiasing
                               | QPainter.TextAntialiasing)

        # 绘制背景色
        self.drawBg(painter)
        # 绘制当前条目选中背景
        self.drawBar(painter)
        # 绘制条目文字
        self.drawText(painter)

    def drawBg(self, painter: QPainter) -> None:
        """ 绘制背景色 """
        painter.save()
        painter.setPen(Qt.NoPen)
        bgGradient: QLinearGradient = QLinearGradient(QPoint(0, 0),
                                                      QPoint(0, self.height()))
        bgGradient.setColorAt(0.0, self.__bgColorStart)
        bgGradient.setColorAt(1.0, self.__bgColorEnd)
        painter.setBrush(bgGradient)
        painter.drawRoundedRect(self.rect(), self.__bgRadius, self.__bgRadius)
        painter.restore()

    def drawBar(self, painter: QPainter) -> None:
        """ 绘制当前条目选中背景 """
        painter.save()
        pen: QPen = QPen()  # PySide2.QtGui.QPen

        barGradient: QLinearGradient = QLinearGradient(
            self.__barRect.topLeft(), self.__barRect.bottomLeft())
        barGradient.setColorAt(0.0, self.__barColorStart)
        barGradient.setColorAt(1.0, self.__barColorEnd)
        painter.setBrush(barGradient)

        if self.barStyle == NavBar.BarStyle.BARSTYLE_RECT:
            painter.setPen(Qt.NoPen)
            painter.drawRoundedRect(self.__barRect, self.__barRadius,
                                    self.__barRadius)
            painter.restore()
            return
        else:
            pen.setWidthF(self.__lineWidth)
            pen.setBrush(barGradient)
            painter.setPen(pen)
            painter.drawRoundedRect(self.__barRect, self.__barRadius,
                                    self.__barRadius)

        pen.setColor(self.__lineColor)
        painter.setPen(pen)

        offset: Decimal = Decimal(self.__lineWidth) / 2
        if self.__barStyle == NavBar.BarStyle.BARSTYLE_LINE_TOP:
            painter.drawLine(int(self.__barRect.left()),
                             self.__barRect.top() + offset,
                             int(self.__barRect.right()),
                             self.__barRect.top() + offset)
        elif self.__barStyle == NavBar.BarStyle.BARSTYLE_LINE_TOP:
            painter.drawLine(self.__barRect.right() - offset,
                             int(self.__barRect.top()),
                             self.__barRect.right() - offset,
                             int(self.__barRect.bottom()))
        elif self.__barStyle == NavBar.BarStyle.BARSTYLE_LINE_TOP:
            painter.drawLine(int(self.__barRect.left()),
                             self.__barRect.bottom() - offset,
                             int(self.__barRect.right()),
                             self.__barRect.bottom() - offset)
        elif self.__barStyle == NavBar.BarStyle.BARSTYLE_LINE_TOP:
            painter.drawLine(self.__barRect.left() + offset,
                             int(self.__barRect.top()),
                             self.__barRect.left() + offset,
                             int(self.__barRect.bottom()))

        # 这里还可以增加右侧倒三角型

        painter.restore()

    def drawText(self, painter: QPainter) -> None:
        """  """
        painter.save()
        textFont: QFont = QFont()
        textFont.setBold(True)
        painter.setFont(textFont)

        count: int = len(self.__listItem)
        self.__initLen = 0

        # 横向导航时,字符区域取条目元素中最长的字符宽度
        longText: str = ""
        for item in self.__items.split("|"):
            if len(item) > len(longText):
                longText = item

        if self.horizontal:
            textLen: Decimal = Decimal(painter.fontMetrics().width(longText))
        else:
            textLen: Decimal = Decimal(painter.fontMetrics().height())

        # 逐个绘制元素列表中的文字及文字背景
        for i in range(count):
            strText: str = self.__listItem[i][0]
            left: QPointF = QPointF(self.__initLen, 0)
            right: QPointF = QPointF(self.__initLen + textLen + self.__space,
                                     self.height())

            if not self.horizontal:
                left = QPointF(0, self.__initLen)
                right = QPointF(self.width(),
                                self.__initLen + textLen + self.__space)

            textRect: QRectF = QRectF(left, right)
            self.__listItem[i][1] = textRect

            if self.__isVirgin:
                self.__barRect = textRect
                self.__isVirgin = False

            # 当前选中区域的文字显示选中文字颜色
            if textRect == self.__listItem[self.__currentIndex][1]:
                painter.setPen(self.__textSelectColor)
            else:
                painter.setPen(self.__textNormalColor)

            painter.drawText(textRect, Qt.AlignCenter, strText)
            self.__initLen += textLen + self.__space

        painter.restore()

    def __slide(self) -> None:
        """ 滑动绘制 """
        if self.__step > 1:
            self.__step -= 1

        if self.horizontal:
            self.__barLen = self.__barRect.topLeft().x()
        else:
            self.__barLen = self.__barRect.topLeft().y()

        if self.__isForward:
            self.__barLen += self.__step
            if self.__barLen >= self.__targetLen:
                self.__barLen = self.__targetLen
                self.__timer.stop()
        else:
            self.__barLen -= self.__step
            if self.__barLen <= self.__targetLen:
                self.__barLen = self.__targetLen
                self.__timer.stop()

        if self.horizontal:
            self.__barRect = QRectF(
                QPointF(self.__barLen, 0),
                QPointF(self.__barLen + self.__barRect.width(), self.height()))
        else:
            self.__barRect = QRectF(
                QPointF(0, self.__barLen),
                QPointF(self.width(), self.__barLen + self.__barRect.height()))

        self.update()

    def getBgColorStart(self) -> QColor:
        """ 读取导航条主背景渐变开始颜色 """
        return self.__bgColorStart

    def setBgColorStart(self, color_start: QColor) -> None:
        """ 设置导航条主背景渐变开始颜色 """
        if self.__bgColorStart != color_start:
            self.__bgColorStart = color_start
            self.update()

    def getBgColorEnd(self) -> QColor:
        """ 读取导航条主背景渐变结束颜色 """
        return self.__bgColorEnd

    def setBgColorEnd(self, color_end: QColor) -> None:
        """ 设置导航条主背景渐变结束颜色 """
        if self.__bgColorEnd != color_end:
            self.__bgColorEnd = color_end
            self.__old_bgColorEnd = color_end
            self.update()

    def getBarColorStart(self) -> QColor:
        """ 读取导航条当前条目渐变开始颜色 """
        return self.__barColorStart

    def setBarColorStart(self, color_start: QColor) -> None:
        """ 设置导航条当前条目渐变开始颜色 """
        if self.__barColorStart != color_start:
            self.__barColorStart = color_start
            self.update()

    def getBarColorEnd(self) -> QColor:
        """ 读取导航条当前条目渐变结束颜色 """
        return self.__barColorEnd

    def setBarColorEnd(self, color_end: QColor) -> None:
        """ 设置导航条当前条目渐变结束颜色 """
        if self.__barColorEnd != color_end:
            self.__barColorEnd = color_end
            self.__old_barColorEnd = color_end
            self.update()

    def getTextNormalColor(self) -> QColor:
        """ 读取文字正常颜色 """
        return self.__textNormalColor

    def setTextNormalColor(self, normal_color: QColor) -> None:
        """ 设置文字正常颜色 """
        if self.__textNormalColor != normal_color:
            self.__textNormalColor = normal_color
            self.update()

    def getTextSelectColor(self) -> QColor:
        """ 读取文字选中颜色 """
        return self.__textSelectColor

    def setTextSelectColor(self, select_color: QColor) -> None:
        """ 设置文字选中颜色 """
        if self.__textSelectColor != select_color:
            self.__textSelectColor = select_color
            self.update()

    def getItems(self) -> str:
        """ 读取所有条目文字信息 """
        return self.__items

    def setItems(self, items: str) -> None:
        """ 设置所有条目文字信息 """
        self.__items = items
        self.__listItem.clear()

        for item in items.split("|"):
            self.__listItem.append([item, QRectF()])

        self.update()

    def getCurrentIndex(self) -> int:
        """ 读取当前选中条目索引 """
        return self.__currentIndex

    def setCurrentIndex(self, index: int) -> None:
        """ 设置当前选中条目索引 """
        self.moveTo_int(index)

    def getCurrentItem(self) -> str:
        """ 读取当前选中条目文字 """
        return self.__currentItem

    def setCurrentItem(self, item: str) -> None:
        """ 设置当前选中条目文字 """
        self.moveTo_str(item)

    def getBgRadius(self) -> int:
        """ 读取背景圆角半径 """
        return self.__bgRadius

    def setBgRadius(self, radius: int) -> None:
        """ 设置背景圆角半径 """
        if self.__bgRadius != radius:
            self.__bgRadius = radius
            self.update()

    def getBarRadius(self) -> int:
        """ 读取选中条目背景圆角半径 """
        return self.__barRadius

    def setBarRadius(self, radius: int) -> None:
        """ 设置选中条目背景圆角半径 """
        if self.__barRadius != radius:
            self.__barRadius = radius
            self.update()

    def getSpace(self) -> int:
        """ 读取条目元素之间的间距 """
        return self.__space

    def setSpace(self, space: int) -> None:
        """ 设置条目元素之间的间距 """
        if self.space != space:
            self.space = space
            self.update()

    def getLineWidth(self) -> int:
        """ 读取线条宽度 """
        return self.__lineWidth

    def setLineWidth(self, line_width: int) -> None:
        """ 设置线条宽度 """
        if self.__lineWidth != line_width:
            self.__lineWidth = line_width
            self.update()

    def getLineColor(self) -> QColor:
        """ 读取线条颜色 """
        return self.__lineColor

    def setLineColor(self, line_color: QColor) -> None:
        """ 设置线条颜色 """
        if self.__lineColor != line_color:
            self.__lineColor = line_color
            self.update()

    def getBarStyle(self) -> BarStyle:
        """ 读取选中元素样式 """
        return self.__barStyle

    def setBarStyle(self, bar_style: BarStyle) -> None:
        """ 设置选中元素样式 """
        if self.__barStyle != bar_style:
            self.__barStyle = bar_style
            self.update()

    def getKeyMove(self) -> bool:
        """ 读取是否支持按键移动 """
        return self.__keyMove

    def setKeyMove(self, key_move: bool) -> None:
        """ 设置是否支持按键移动 """
        if self.__keyMove != key_move:
            self.__keyMove = key_move
            if key_move:
                self.setFocusPolicy(Qt.StrongFocus)
            else:
                self.setFocusPolicy(Qt.NoFocus)

    def getHorizontal(self) -> bool:
        """ 读取是否横向显示 """
        return self.__horizontal

    def setHorizontal(self, horizontal: bool) -> None:
        """ 设置是否横向显示 """
        if self.__horizontal != horizontal:
            self.__horizontal = horizontal
            self.update()

    def getFlat(self) -> bool:
        """ 读取是否扁平化 """
        return self.__flat

    def setFlat(self, flat: bool) -> None:
        """ 设置是否扁平化 """
        if self.__flat != flat:
            # 扁平后将初始颜色赋值给结束颜色达到扁平的效果,如果取消扁平则再次恢复原有的颜色
            if flat:
                self.__bgColorEnd = self.__bgColorStart
                self.__barColorEnd = self.__barColorStart
            else:
                self.__bgColorEnd = self.__old_bgColorEnd
                self.__barColorEnd = self.__old_barColorEnd

            self.__flat = flat
            self.update()

    def sizeHint(self) -> QSize:
        """ 返回控件默认大小 """
        return QSize(400, 30)

    def minimumSizeHint(self) -> QSize:
        """ 返回控件最小大小 """
        return QSize(30, 30)

    def clearItem(self) -> None:
        """ 删除所有条目 """
        self.__listItem.clear()
        self.update()

    def moveFirst(self) -> None:
        """ 移动到第一个条目 """
        index: int = 0
        if self.__currentIndex != index:
            self.moveTo_int(index)

    def moveLast(self) -> None:
        """ 移动到最后一个条目 """
        index = len(self.__listItem) - 1
        if self.__currentIndex != index:
            self.moveTo_int(index)

    def movePrevious(self) -> None:
        """ 往前移动条目 """
        if self.__currentIndex > 0:
            self.__currentIndex -= 1
            self.moveTo_int(self.__currentIndex)

    def moveNext(self) -> None:
        """ 往后移动条目 """
        if self.__currentIndex < (len(self.__listItem) - 1):
            self.__currentIndex += 1
            self.moveTo_int(self.__currentIndex)

    def moveTo_int(self, index: int) -> None:
        """ 移动到指定索引条目 """
        if (index >= 0) and (len(self.__listItem) > index):
            rec: QRectF = QRectF(self.__listItem[index][1])
            pos: QPoint = QPoint(int(rec.x()), int(rec.y()))
            self.moveTo_point(pos)

    def moveTo_str(self, item: str) -> None:
        """ 移动到指定文字条目 """
        count: int = len(self.__listItem)
        for i in range(count):
            if self.__listItem[i][0] == item:
                self.moveTo_int(i)
                break

    def moveTo_point(self, point: QPointF) -> None:
        """ 移动到指定坐标位置条目 """
        count: int = len(self.__listItem)
        for i in range(count):
            # 如果不是最后一个,则辨别指定项
            if i != (count - 1):
                # 辨别方法,如果不在两项之间,则不是指定项
                if self.__horizontal:
                    if not (
                        (point.x() >= self.__listItem[i][1].topLeft().x()) and
                        (point.x() < self.__listItem[i + 1][1].topLeft().x())):
                        continue
                else:
                    if not (
                        (point.y() >= self.__listItem[i][1].topLeft().y()) and
                        (point.y() < self.__listItem[i + 1][1].topLeft().y())):
                        continue

            self.__currentIndex = i
            self.__currentItem = self.__listItem[i][0]
            self.__targetRect = self.__listItem[i][1]

            if self.__horizontal:
                self.__targetLen = self.__targetRect.topLeft().x()
                self.__barLen = self.__barRect.topLeft().x()
            else:
                self.__targetLen = self.__targetRect.topLeft().y()
                self.__barLen = self.__barRect.topLeft().y()

            self.__isForward = (self.__targetLen > self.__barLen)
            distance: int = int(abs(self.__targetLen - self.__barLen))

            # 重新获取每次移动的步长
            self.__step = self.__initStep(int(distance))
            self.__timer.start()

            self.currentItemChanged.emit(self.__currentIndex,
                                         self.__currentItem)
            break

    bgColorStart: QColor = property(fget=getBgColorStart,
                                    fset=setBgColorStart,
                                    fdel=None,
                                    doc="导航条主背景渐变开始颜色")
    bgColorEnd: QColor = property(fget=getBgColorEnd,
                                  fset=setBgColorEnd,
                                  fdel=None,
                                  doc="导航条主背景渐变结束颜色")

    barColorStart: QColor = property(fget=getBarColorStart,
                                     fset=setBarColorStart,
                                     fdel=None,
                                     doc="导航条当前条目渐变开始颜色")
    barColorEnd: QColor = property(fget=getBarColorEnd,
                                   fset=setBarColorEnd,
                                   fdel=None,
                                   doc="导航条当前条目渐变结束颜色")

    textNormalColor: QColor = property(fget=getTextNormalColor,
                                       fset=setTextNormalColor,
                                       fdel=None,
                                       doc="文字正常颜色")
    textSelectColor: QColor = property(fget=getTextSelectColor,
                                       fset=setTextSelectColor,
                                       fdel=None,
                                       doc="文字选中颜色")

    items: str = property(fget=getItems,
                          fset=setItems,
                          fdel=None,
                          doc="所有条目文字信息")
    currentIndex: int = property(fget=getCurrentIndex,
                                 fset=setCurrentIndex,
                                 fdel=None,
                                 doc="当前选中条目索引")
    currentItem: str = property(fget=getCurrentItem,
                                fset=setCurrentItem,
                                fdel=None,
                                doc="当前选中条目文字")

    bgRadius: int = property(fget=getBgRadius,
                             fset=setBgRadius,
                             fdel=None,
                             doc="背景圆角半径")
    barRadius: int = property(fget=getBarRadius,
                              fset=setBarRadius,
                              fdel=None,
                              doc="选中条目背景圆角半径")
    space: int = property(fget=getSpace,
                          fset=setSpace,
                          fdel=None,
                          doc="条目元素之间的间距")

    lineWidth: int = property(fget=getLineWidth,
                              fset=setLineWidth,
                              fdel=None,
                              doc="线条宽度")
    lineColor: QColor = property(fget=getLineColor,
                                 fset=setLineColor,
                                 fdel=None,
                                 doc="线条颜色")

    barStyle: BarStyle = property(fget=getBarStyle,
                                  fset=setBarStyle,
                                  fdel=None,
                                  doc="选中元素样式")

    keyMove: bool = property(fget=getKeyMove,
                             fset=setKeyMove,
                             fdel=None,
                             doc="是否支持按键移动")
    horizontal: bool = property(fget=getHorizontal,
                                fset=setHorizontal,
                                fdel=None,
                                doc="是否横向显示")
    flat: bool = property(fget=getFlat, fset=setFlat, fdel=None, doc="是否扁平化")