import numpy as np from PySide6.QtCore import QRectF, Qt from PySide6.QtGui import QColor, QFont, QPainter, QPen class CanvasRenderMixin: def paintEvent(self, event): painter = QPainter(self) painter.fillRect(self.rect(), self.OFF_CANVAS_COLOR) if self.image is None: return img_rect = self._image_rect_view() painter.drawImage(img_rect, self.image) label_font = QFont(painter.font()) label_font.setPointSize(18) label_font.setBold(True) for si, s in enumerate(self.slices): points = [self._image_to_view(p) for p in s.bbox] for i in range(4): a = points[i] b = points[(i + 1) % 4] if i == 0: color = QColor("red") elif i == 1: color = QColor("green") elif i == 2: color = QColor("orange") else: color = QColor("blue") if s.locked else QColor("lightgreen") painter.setPen(QPen(color, 3)) painter.drawLine(a, b) # Corners are color-coded: left = orange, right = cyan. # Edge 0 (top, red) runs TL->TR, so corners 0 and 3 are the left # side and corners 1 and 2 are the right side. corner_colors = (QColor("orange"), QColor("cyan"), QColor("cyan"), QColor("orange")) for p, color in zip(points, corner_colors): painter.setPen(QPen(QColor("blue"), 2)) painter.setBrush(color) painter.drawRect(QRectF(p.x() - 5, p.y() - 5, 10, 10)) center = np.mean(s.bbox, axis=0) center_view = self._image_to_view(center) if si == self.active_slice_index: text_color = QColor("gold") else: text_color = QColor("blue") if s.locked else QColor("lightgreen") painter.setPen(QPen(text_color, 1)) painter.setFont(label_font) painter.drawText( QRectF(center_view.x() - 20, center_view.y() - 16, 40, 32), Qt.AlignCenter, str(si), ) if s.side_handles_enabled and s.is_perfect_rectangle(): handle_color = QColor("orange") if si == self.active_slice_index else QColor(255, 170, 0) painter.setPen(QPen(handle_color, 2)) painter.setBrush(QColor(handle_color.red(), handle_color.green(), handle_color.blue(), 170)) handle_size = ( float(getattr(self, "SIDE_HANDLE_SIZE_ACTIVE", 11.0)) if si == self.active_slice_index else float(getattr(self, "SIDE_HANDLE_SIZE_INACTIVE", 9.0)) ) for ei in range(4): mid = (s.bbox[ei] + s.bbox[(ei + 1) % 4]) / 2.0 mid_view = self._image_to_view(mid) painter.drawRect( QRectF( mid_view.x() - handle_size / 2.0, mid_view.y() - handle_size / 2.0, handle_size, handle_size, ) )