From 5b46d83856a6abc7962aa88340a4aa2490df2b63 Mon Sep 17 00:00:00 2001 From: Francesco Padovani Date: Tue, 4 Mar 2025 21:22:34 +0100 Subject: [PATCH] feat: show mirrored cursor on slideshow window, see #612 --- cellacdc/apps.py | 41 ++++++++++++++++++++++++++++++++++++++++- cellacdc/gui.py | 22 ++++++++++++++++++++-- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/cellacdc/apps.py b/cellacdc/apps.py index 0ff2b6a8..e91e8295 100755 --- a/cellacdc/apps.py +++ b/cellacdc/apps.py @@ -6607,17 +6607,19 @@ def closeEvent(self, event): class imageViewer(QMainWindow): """Main Window.""" sigClosed = Signal() + sigHoveringImage = Signal(object, object) def __init__( self, parent=None, posData=None, button_toUncheck=None, spinBox=None, linkWindow=None, enableOverlay=False, - isSigleFrame=False + isSigleFrame=False, enableMirroredCursor=False ): self.button_toUncheck = button_toUncheck self.parent = parent self.posData = posData self.spinBox = spinBox self.linkWindow = linkWindow + self.enableMirroredCursor = enableMirroredCursor self.isSigleFrame = isSigleFrame self.minMaxValuesMapper = None """Initializer.""" @@ -6642,6 +6644,8 @@ def __init__( self.gui_connectActions() self.gui_setSingleFrameMode(self.isSigleFrame) + + self.setupMirroredCursor() mainContainer = QWidget() self.setCentralWidget(mainContainer) @@ -6704,7 +6708,21 @@ def gui_createToolBars(self): self.linkWindowCheckbox = QCheckBox("Link to main GUI") self.linkWindowCheckbox.setChecked(True) editToolBar.addWidget(self.linkWindowCheckbox) + + if self.enableMirroredCursor: + self.showMirroredCursorCheckbox = QCheckBox( + 'Show mirrored cursor from main window' + ) + self.showMirroredCursorCheckbox.setChecked(True) + editToolBar.addWidget(self.showMirroredCursorCheckbox) + def setupMirroredCursor(self): + self.cursor = pg.ScatterPlotItem( + symbol='+', pxMode=True, pen=pg.mkPen('k', width=1), + brush=pg.mkBrush('w'), size=16, tip=None + ) + self.Plot.addItem(self.cursor) + def gui_connectActions(self): self.exitAction.triggered.connect(self.close) self.prevAction.triggered.connect(self.prev_frame) @@ -6933,6 +6951,15 @@ def getOverlayItems(self, channelName): alphaScrollBar = self.addAlphaScrollbar(channelName, imageItem) return imageItem, lutItem, alphaScrollBar + def setMirroredCursorPos(self, x, y): + if not self.enableMirroredCursor: + return + + if not self.showMirroredCursorCheckbox.isChecked(): + return + + self.cursor.setData([x], [y]) + def setOverlayColors(self): self.overlayRGBs = [ (255, 255, 0), @@ -7147,6 +7174,18 @@ def gui_hoverEventImg(self, event): self.wcLabel.setText(f'') except Exception as e: self.wcLabel.setText(f'') + + emitHovering = ( + self.enableMirroredCursor and + self.showMirroredCursorCheckbox.isChecked() + ) + if emitHovering: + if event.isExit(): + x, y = None, None + else: + x, y = event.pos() + self.sigHoveringImage.emit(x, y) + self.cursor.setData([], []) def next_frame(self): if self.frame_i < self.num_frames-1: diff --git a/cellacdc/gui.py b/cellacdc/gui.py index 2ff8560d..777b4034 100755 --- a/cellacdc/gui.py +++ b/cellacdc/gui.py @@ -6627,7 +6627,10 @@ def gui_hoverEventImg1(self, event, isHoverImg1=True): if event.isExit(): self.resetCursor() - + + if not event.isExit() and self.slideshowWin is not None: + self.slideshowWin.setMirroredCursorPos(*event.pos()) + # Alt key was released --> restore cursor modifiers = QGuiApplication.keyboardModifiers() cursorsInfo = self.gui_setCursor(modifiers, event) @@ -12748,7 +12751,8 @@ def launchSlideshow(self): parent=self, button_toUncheck=self.slideshowButton, linkWindow=posData.SizeT > 1, - enableOverlay=True + enableOverlay=True, + enableMirroredCursor=True ) self.slideshowWin.img.minMaxValuesMapper = ( self.img1.minMaxValuesMapper @@ -12759,6 +12763,9 @@ def launchSlideshow(self): self.slideshowWin.overlayButton.setChecked( self.overlayButton.isChecked() ) + self.slideshowWin.sigHoveringImage.connect( + self.setMirroredCursorFromSecondWindow + ) if posData.SizeZ > 1: z_slice = self.zSliceScrollBar.sliderPosition() self.slideshowWin.img.setCurrentZsliceIndex(z_slice) @@ -12774,6 +12781,16 @@ def launchSlideshow(self): self.slideshowWin.close() self.slideshowWin = None + def setMirroredCursorFromSecondWindow(self, x, y): + if x is None: + xx, yy = [], [] + else: + xx, yy = [x], [y] + self.ax1_cursor.setData(xx, yy) + if not self.isTwoImageLayout: + return + self.ax2_cursor.setData(xx, yy) + def goToZsliceSearchedID(self, obj): if not self.isSegm3D: return @@ -23888,6 +23905,7 @@ def highlightZneighLabels_cb(self, checked): pass def setTwoImagesLayout(self, isTwoImages): + self.isTwoImageLayout = isTwoImages if isTwoImages: self.graphLayout.removeItem(self.titleLabel) self.graphLayout.addItem(self.titleLabel, row=0, col=1, colspan=2)