from PyQt5.QtWidgets import ( QGraphicsScene, QGraphicsPixmapItem, QPushButton, QHBoxLayout, QVBoxLayout, QWidget, QSlider, QLabel ) from PyQt5.QtGui import QFont from PyQt5.QtCore import Qt, QRectF, QSize from circleEditorGraphicsView import CircleEditorGraphicsView from draggableCircleItem import DraggableCircleItem class CircleEditorWidget(QWidget): def __init__(self, pixmap, init_radius=20, done_callback=None, parent=None): super().__init__(parent) self._pixmap = pixmap self._done_callback = done_callback self._init_radius = init_radius layout = QVBoxLayout(self) self.setLayout(layout) # # 1) ADD A CENTERED LABEL ABOVE THE IMAGE, WITH BIGGER FONT # label_instructions = QLabel("Scale the dot to be of the size of your ridge") label_instructions.setAlignment(Qt.AlignCenter) big_font = QFont("Arial", 20) big_font.setBold(True) label_instructions.setFont(big_font) layout.addWidget(label_instructions) # # 2) THE SPECIALIZED GRAPHICS VIEW THAT SHOWS THE IMAGE # self._graphics_view = CircleEditorGraphicsView(circle_editor_widget=self) self._scene = QGraphicsScene(self) self._graphics_view.setScene(self._scene) layout.addWidget(self._graphics_view) # Show the image self._image_item = QGraphicsPixmapItem(self._pixmap) self._scene.addItem(self._image_item) # Put circle in center cx = self._pixmap.width() / 2 cy = self._pixmap.height() / 2 self._circle_item = DraggableCircleItem(cx, cy, radius=self._init_radius, color=Qt.red) self._scene.addItem(self._circle_item) # Fit in view self._graphics_view.setSceneRect(QRectF(self._pixmap.rect())) self._graphics_view.fitInView(self._image_item, Qt.KeepAspectRatio) # # 3) CONTROLS BELOW # bottom_layout = QHBoxLayout() layout.addLayout(bottom_layout) # label + slider self._lbl_size = QLabel(f"size ({self._init_radius})") bottom_layout.addWidget(self._lbl_size) self._slider = QSlider(Qt.Horizontal) self._slider.setRange(1, 200) self._slider.setValue(self._init_radius) bottom_layout.addWidget(self._slider) # done button self._btn_done = QPushButton("Done") bottom_layout.addWidget(self._btn_done) # Connect signals self._slider.valueChanged.connect(self._on_slider_changed) self._btn_done.clicked.connect(self._on_done_clicked) def _on_slider_changed(self, value): self._circle_item.set_radius(value) self._lbl_size.setText(f"size ({value})") def _on_done_clicked(self): final_radius = self._circle_item.radius() if self._done_callback is not None: self._done_callback(final_radius) def update_slider_value(self, new_radius): self._slider.blockSignals(True) self._slider.setValue(new_radius) self._slider.blockSignals(False) self._lbl_size.setText(f"size ({new_radius})") def sizeHint(self): return QSize(800, 600)