Files
aza/APP/logo-tool/ui/canvas_widget.py
2026-03-30 07:59:11 +02:00

116 lines
4.0 KiB
Python

"""
Zentrales Canvas-Widget: zeigt das Logo mit Zoom, Pan und Rasterlinien an.
"""
from __future__ import annotations
from PySide6.QtWidgets import QGraphicsView, QGraphicsScene, QGraphicsPixmapItem
from PySide6.QtCore import Qt, Signal, QPointF
from PySide6.QtGui import (
QPainter, QPen, QColor, QPixmap, QWheelEvent, QMouseEvent,
)
class LogoCanvas(QGraphicsView):
zoom_changed = Signal(float)
def __init__(self, parent=None):
super().__init__(parent)
self._scene = QGraphicsScene(self)
self.setScene(self._scene)
self._pixmap_item: QGraphicsPixmapItem | None = None
self._overlay_item: QGraphicsPixmapItem | None = None
self._zoom = 1.0
self._pan_active = False
self._pan_start = QPointF()
self.setRenderHints(
QPainter.RenderHint.Antialiasing
| QPainter.RenderHint.SmoothPixmapTransform
)
self.setDragMode(QGraphicsView.DragMode.NoDrag)
self.setTransformationAnchor(QGraphicsView.ViewportAnchor.AnchorUnderMouse)
self.setBackgroundBrush(QColor("#2b2b2b"))
self.setMinimumSize(400, 300)
self._draw_checkerboard()
def _draw_checkerboard(self):
"""Schachbrettmuster als Transparenz-Indikator."""
self.setStyleSheet("""
QGraphicsView {
background-color: #2b2b2b;
}
""")
def set_original_image(self, pixmap: QPixmap):
"""Zeigt das Original-PNG an."""
if self._pixmap_item:
self._scene.removeItem(self._pixmap_item)
self._pixmap_item = self._scene.addPixmap(pixmap)
self._pixmap_item.setZValue(0)
self.fitInView(self._pixmap_item, Qt.AspectRatioMode.KeepAspectRatio)
self._zoom = self.transform().m11()
self.zoom_changed.emit(self._zoom)
def set_overlay(self, pixmap: QPixmap):
"""Zeigt die gerenderten Vektorpfade als Overlay an."""
if self._overlay_item:
self._scene.removeItem(self._overlay_item)
self._overlay_item = self._scene.addPixmap(pixmap)
self._overlay_item.setZValue(1)
self._overlay_item.setOpacity(0.85)
def clear_overlay(self):
if self._overlay_item:
self._scene.removeItem(self._overlay_item)
self._overlay_item = None
# --- Zoom via Mausrad ---
def wheelEvent(self, event: QWheelEvent):
factor = 1.15 if event.angleDelta().y() > 0 else 1 / 1.15
self._zoom *= factor
self.scale(factor, factor)
self.zoom_changed.emit(self._zoom)
# --- Pan via mittlere Maustaste oder Leertaste + Links ---
def mousePressEvent(self, event: QMouseEvent):
if event.button() == Qt.MouseButton.MiddleButton:
self._pan_active = True
self._pan_start = event.position()
self.setCursor(Qt.CursorShape.ClosedHandCursor)
else:
super().mousePressEvent(event)
def mouseMoveEvent(self, event: QMouseEvent):
if self._pan_active:
delta = event.position() - self._pan_start
self._pan_start = event.position()
self.horizontalScrollBar().setValue(
self.horizontalScrollBar().value() - int(delta.x())
)
self.verticalScrollBar().setValue(
self.verticalScrollBar().value() - int(delta.y())
)
else:
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event: QMouseEvent):
if event.button() == Qt.MouseButton.MiddleButton:
self._pan_active = False
self.setCursor(Qt.CursorShape.ArrowCursor)
else:
super().mouseReleaseEvent(event)
def set_zoom(self, zoom: float):
factor = zoom / self._zoom
self._zoom = zoom
self.scale(factor, factor)
self.zoom_changed.emit(self._zoom)
def fit_to_view(self):
if self._pixmap_item:
self.fitInView(self._pixmap_item, Qt.AspectRatioMode.KeepAspectRatio)
self._zoom = self.transform().m11()
self.zoom_changed.emit(self._zoom)