From ac3a16102efd8608093e6d2c0669cfd463b9e083 Mon Sep 17 00:00:00 2001 From: ryoMax Date: Mon, 30 Mar 2026 13:25:27 +0900 Subject: [PATCH] fix: improve macOS UX (HiDPI support and native key labels) - Use QKeySequence.NativeText for undo/redo tooltips so they show Cmd+Z / Cmd+Shift+Z on macOS instead of Ctrl+Z / Ctrl+Y - Add devicePixelRatio handling in PreviewWidget and MaskCanvas for crisp rendering on Retina displays --- mask_canvas.py | 3 +++ mask_composer.py | 4 ++-- parts_mixer.py | 4 ++-- preview_widget.py | 17 ++++++++++++++--- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/mask_canvas.py b/mask_canvas.py index 8542b09..829c1b9 100644 --- a/mask_canvas.py +++ b/mask_canvas.py @@ -246,6 +246,7 @@ def paintEvent(self, event): Qt.KeepAspectRatio, Qt.SmoothTransformation ) + scaled_pixmap.setDevicePixelRatio(self.screen().devicePixelRatio() if self.screen() else 1.0) painter.drawPixmap(0, 0, scaled_pixmap) # マスクオーバーレイを描画 @@ -298,6 +299,8 @@ def _create_mask_overlay(self) -> QPixmap: Qt.SmoothTransformation ) + scaled_pixmap.setDevicePixelRatio(self.screen().devicePixelRatio() if self.screen() else 1.0) + return scaled_pixmap def mousePressEvent(self, event): diff --git a/mask_composer.py b/mask_composer.py index b3145d8..fb050b4 100644 --- a/mask_composer.py +++ b/mask_composer.py @@ -337,12 +337,12 @@ def _setup_ui(self): # Undo/Redoボタン undo_redo_layout = QHBoxLayout() self.btn_undo = QPushButton('戻す') - self.btn_undo.setToolTip('Ctrl+Z') + self.btn_undo.setToolTip(QKeySequence(QKeySequence.StandardKey.Undo).toString(QKeySequence.SequenceFormat.NativeText)) self.btn_undo.clicked.connect(self._on_undo) undo_redo_layout.addWidget(self.btn_undo) self.btn_redo = QPushButton('やり直し') - self.btn_redo.setToolTip('Ctrl+Y') + self.btn_redo.setToolTip(QKeySequence(QKeySequence.StandardKey.Redo).toString(QKeySequence.SequenceFormat.NativeText)) self.btn_redo.clicked.connect(self._on_redo) undo_redo_layout.addWidget(self.btn_redo) brush_layout.addLayout(undo_redo_layout) diff --git a/parts_mixer.py b/parts_mixer.py index a5a13e9..8776eec 100644 --- a/parts_mixer.py +++ b/parts_mixer.py @@ -340,12 +340,12 @@ def _setup_ui(self): # Undo/Redo undo_layout = QHBoxLayout() self.btn_undo = QPushButton('戻す') - self.btn_undo.setToolTip('Ctrl+Z') + self.btn_undo.setToolTip(QKeySequence(QKeySequence.StandardKey.Undo).toString(QKeySequence.SequenceFormat.NativeText)) self.btn_undo.clicked.connect(self._on_undo) undo_layout.addWidget(self.btn_undo) self.btn_redo = QPushButton('やり直し') - self.btn_redo.setToolTip('Ctrl+Y') + self.btn_redo.setToolTip(QKeySequence(QKeySequence.StandardKey.Redo).toString(QKeySequence.SequenceFormat.NativeText)) self.btn_redo.clicked.connect(self._on_redo) undo_layout.addWidget(self.btn_redo) brush_layout.addLayout(undo_layout) diff --git a/preview_widget.py b/preview_widget.py index cd53eab..f29283c 100644 --- a/preview_widget.py +++ b/preview_widget.py @@ -184,16 +184,20 @@ def update_display(self): return # スケール適用 - if self.scale != 1.0: + # Apply scale and device pixel ratio for HiDPI displays + dpr = self._device_pixel_ratio() + effective_scale = self.scale * dpr + if effective_scale != 1.0: h, w = display.shape[:2] - new_w = int(w * self.scale) - new_h = int(h * self.scale) + new_w = max(1, int(w * effective_scale)) + new_h = max(1, int(h * effective_scale)) display = cv2.resize(display, (new_w, new_h), interpolation=cv2.INTER_NEAREST) # QImageに変換 try: qimage = convert_to_qimage(display) pixmap = QPixmap.fromImage(qimage) + pixmap.setDevicePixelRatio(dpr) self.label.setPixmap(pixmap) except Exception as e: print(f"Display error: {e}") @@ -381,6 +385,13 @@ def mouseReleaseEvent(self, event: QMouseEvent): # ブラシモード self.mouse_released.emit(img_x, img_y) + def _device_pixel_ratio(self) -> float: + """Get the device pixel ratio for HiDPI support.""" + screen = self.screen() + if screen is not None: + return screen.devicePixelRatio() + return 1.0 + def wheelEvent(self, event): """ホイールイベント(ズーム)""" delta = event.angleDelta().y()