From 798e52aeade9fd6a3cc0e5b7b5f69265c5c40e41 Mon Sep 17 00:00:00 2001 From: Michael Rariden Date: Thu, 21 May 2026 15:31:41 -0400 Subject: [PATCH 1/6] move sliders to guiparts, add slider popup dialog, rewire slider signals --- cellpose/gui/gui.py | 89 ++++++++++++-------- cellpose/gui/guiparts.py | 178 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 231 insertions(+), 36 deletions(-) diff --git a/cellpose/gui/gui.py b/cellpose/gui/gui.py index e79004e7..4ced7c70 100644 --- a/cellpose/gui/gui.py +++ b/cellpose/gui/gui.py @@ -6,16 +6,18 @@ import sys, os, pathlib, warnings, datetime, time, copy from qtpy import QtGui, QtCore -from superqt import QRangeSlider, QCollapsible +from superqt import QCollapsible from qtpy.QtWidgets import QScrollArea, QMainWindow, QApplication, QWidget, QScrollBar, \ QComboBox, QGridLayout, QPushButton, QFrame, QCheckBox, QLabel, QProgressBar, \ - QLineEdit, QMessageBox, QGroupBox, QMenu, QAction + QLineEdit, QMessageBox, QGroupBox, QMenu, QAction, QHBoxLayout import pyqtgraph as pg import numpy as np from scipy.stats import mode import cv2 +from cellpose.gui.guiparts import ClickableSlider, SaturationSliderDialog + from . import guiparts, menus, io from .. import models, core, dynamics, version, train from ..utils import download_url_to_file, masks_to_outlines, diameters @@ -30,27 +32,6 @@ except: MATPLOTLIB = False -Horizontal = QtCore.Qt.Orientation.Horizontal - - -class Slider(QRangeSlider): - - def __init__(self, parent, name, color): - super().__init__(Horizontal) - self.setEnabled(False) - self.valueChanged.connect(lambda: self.levelChanged(parent)) - self.name = name - - self.setStyleSheet(""" QSlider{ - background-color: transparent; - } - """) - self.show() - - def levelChanged(self, parent): - parent.level_change(self.name) - - class QHLine(QFrame): def __init__(self): @@ -394,13 +375,15 @@ def make_buttons(self): label.setStyleSheet(f"color: {colornames[r]}") label.setFont(self.boldmedfont) self.satBoxG.addWidget(label, widget_row, 0, 1, 2) - self.sliders.append(Slider(self, names[r], colors[r])) + self.sliders.append(ClickableSlider(self)) self.sliders[-1].setMinimum(-.1) self.sliders[-1].setMaximum(255.1) self.sliders[-1].setValue([0, 255]) - self.sliders[-1].setToolTip( - "NOTE: manually changing the saturation bars does not affect normalization in segmentation" + self.sliders[-1].setToolTip("Right click to pop out slider.\n" + + "NOTE: this saturation bar does not affect normalization in segmentation" ) + self.sliders[-1].sigRightClick.connect(lambda r=r:self.open_slider_popup(r)) + self.sliders[-1].valueChanged.connect(lambda value, r=r: self.color_level_change(value, r)) self.satBoxG.addWidget(self.sliders[-1], widget_row, 2, 1, 7) b += 1 @@ -660,17 +643,51 @@ def make_buttons(self): return b + + def open_slider_popup(self, r:int) -> None: + """ Open slider popup and attach it to the color index `r`. + Clicking off of the popup causes it to close. + + Args: + r (int): The index of the color slider (0, 1, 2). + """ + assert r in [0, 1, 2], f'The color index, `r`, must be in (0, 1, 2), got {r}' + low, high = self.saturation[r][self.currentZ] + low = int(low) + high = int(high) + dialog = SaturationSliderDialog(self, low=low, high=high) + dialog.valueChanged.connect(lambda val, r=r: self.color_level_change(val, r)) + dialog.show() + dialog.setWindowFlags(QtCore.Qt.Popup) # make it stationary and temporary + dialog.show() + + # move the dialog to the top of the window: + global_pos = self.win.mapToGlobal(QtCore.QPoint(0, 0)) + x_pad = 10 + y_offset = 100 + x = global_pos.x() + x_pad + y = global_pos.y() + y_offset + dialog.move(x, y) + dialog.setFixedWidth(self.win.width() - 2*x_pad) + + + def color_level_change(self, lohi:tuple, r:int) -> None: + """ Set the saturation attribute for the color `r` to `lowhi` and + call self.update_plot(). Also, update all the layers if self.autobtn + is unchecked. + + Args: + lohi (tuple): Tuple of (low, high) values for the saturation/slider. + r (int): The index of the color to adjust. + """ + self.saturation[r][self.currentZ] = lohi + # update all the layers if autobtn is unchecked + if not self.autobtn.isChecked(): + for r in range(3): + for i in range(len(self.saturation[r])): + self.saturation[r][i] = self.saturation[r][self.currentZ] + self.update_plot() - def level_change(self, r): - r = ["red", "green", "blue"].index(r) - if self.loaded: - sval = self.sliders[r].value() - self.saturation[r][self.currentZ] = sval - if not self.autobtn.isChecked(): - for r in range(3): - for i in range(len(self.saturation[r])): - self.saturation[r][i] = self.saturation[r][self.currentZ] - self.update_plot() def keyPressEvent(self, event): event.ignore() diff --git a/cellpose/gui/guiparts.py b/cellpose/gui/guiparts.py index 71086f82..b0e9ae7a 100644 --- a/cellpose/gui/guiparts.py +++ b/cellpose/gui/guiparts.py @@ -10,6 +10,8 @@ import numpy as np import pathlib, os +from superqt import QRangeSlider + from cellpose.gui.io import _save_sets @@ -834,3 +836,179 @@ def setDrawKernel(self, kernel_size=3): opamask = 100 * kernel[:, :, np.newaxis] self.redmask = np.concatenate((onmask, offmask, offmask, onmask), axis=-1) self.strokemask = np.concatenate((onmask, offmask, onmask, opamask), axis=-1) + + +Horizontal = QtCore.Qt.Orientation.Horizontal + + +class BaseSlider(QRangeSlider): + """ Base slider with style sheet definition and horizontal orientation + + Relies on built-in `.valueChanged()` method""" + def __init__(self, parent): + super().__init__(Horizontal) + self.setParent(parent) + self.setEnabled(False) + self.setStyleSheet(""" QSlider{ + background-color: transparent; + } + """) + self.show() + + +class Slider(BaseSlider): + """ Simple slider """ + def __init__(self, parent): + super().__init__(parent) + + +class SaturationSliderDialog(QDialog): + """ Slider dialog with signal for reporting the slider changes + + Internally, the textboxes listen to and update the slider values, and + only the slider values are used in the valueChanged interface. + """ + + valueChanged = QtCore.Signal(tuple) + + def __init__(self, parent: QWidget, low:int|None=None, high:int|None=None, dtype:str|np.dtype|None=None): + """ Slider dialog with signal for report slider changes. After instantiation, + hook up the `.valueChanged` to listen for events from this widget. + + Args: + parent (QWidget): A Qt widget from which this object can be referenced. + low (int | None, optional): The low value to initialize the slider. Defaults to dtype.min. + high (int | None, optional): The high value to initialize the slider. Defaults to dtype.max. + dtype (np.dtype | None, optional): . Defaults to np.uint8. + """ + super().__init__(parent) + + if not dtype: + dtype = np.dtype(np.uint8) + + try: + dtype = np.dtype(dtype) + except TypeError: + raise TypeError(f"Expected valid numpy data type, got {type(dtype)}") + + dtype_min = np.iinfo(dtype).min + dtype_max = np.iinfo(dtype).max + + if not low: + low = dtype_min + if not high: + high = dtype_max + + self.slider = Slider(self) + layout = QGridLayout(self) + low_textbox = QLineEdit(self) + low_textbox.setFixedWidth(50) + low_textbox.textChanged.connect(self._validate_update_low_textbox) + self.low_textbox = low_textbox + + high_textbox = QLineEdit(self) + high_textbox.setFixedWidth(50) + high_textbox.textChanged.connect(self._validate_update_high_textbox) + self.high_textbox = high_textbox + + layout.addWidget(low_textbox, 0, 0) + layout.addWidget(self.slider, 0, 1) + layout.addWidget(high_textbox, 0, 2) + layout.setColumnStretch(1, 1) + self.setLayout(layout) + + self.slider.setMinimum(dtype_min) + self.slider.setMaximum(dtype_max) + self.slider.setValue([dtype_min, dtype_max]) + self.slider.setEnabled(True) + self.slider.valueChanged.connect(self.slider_changed) + + self._low = low + self._high = high + self.low_textbox.setText(str(low)) + self.high_textbox.setText(str(high)) + + + def _validate_text_input(self, value) -> int: + """ Convert textbox input into ``int`` """ + if len(value) < 1: + value = 0 + return int(value) + + + def _validate_update_low_textbox(self) -> None: + """ Validate textbox input and set slider low value """ + low = self._validate_text_input(self.low_textbox.text()) + high = self.slider.value()[1] + if low <= high: + self.slider.setValue((low, high)) + + + def _validate_update_high_textbox(self) -> None: + """ Validate textbox input and set slider high value """ + low = self.slider.value()[0] + high = self._validate_text_input(self.high_textbox.text()) + if low <= high: + self.slider.setValue((low, high)) + + + @property + def low(self) -> int: + """ slider low value """ + return self._low + + + @low.setter + def low(self, value:int) -> None: + """ set `value` must be <= self.high, otherwise ignored""" + if value == self._low: + return + if value > self.high: + return + self._low = value + self.low_textbox.setText(str(value)) + self._update_validators() + + + @property + def high(self) -> int: + """ slider high value""" + return self._high + + + @high.setter + def high(self, value:int) -> None: + """ set `value` must be >= self.low, otherwise ignored """ + if value == self._high: + return + if value < self.low: + return + self._high = value + self.high_textbox.setText(str(value)) + self._update_validators() + + + def _update_validators(self) -> None: + """ Update the textbox validators after editing """ + self.high_textbox.setValidator(QtGui.QIntValidator(self.low, 255)) + self.low_textbox.setValidator(QtGui.QIntValidator(0, self.high)) + + + def slider_changed(self, lohi) -> None: + """ Set the low and high values and emit the valueChagned signal. """ + lo, hi = lohi + self.low = lo + self.high = hi + self.valueChanged.emit(lohi) + + +class ClickableSlider(BaseSlider): + """ Slider that emits a signal on right click """ + sigRightClick = QtCore.Signal() + + def __init__(self, parent): + super().__init__(parent) + + def contextMenuEvent(self, event): + self.sigRightClick.emit() + event.accept() From fb4f02f28fceae1be49e483fdae4cd6b340d3cc7 Mon Sep 17 00:00:00 2001 From: Michael Rariden Date: Thu, 21 May 2026 15:32:15 -0400 Subject: [PATCH 2/6] only listen to escape during drawing to prevent blocking --- cellpose/gui/gui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cellpose/gui/gui.py b/cellpose/gui/gui.py index 4ced7c70..35616bb6 100644 --- a/cellpose/gui/gui.py +++ b/cellpose/gui/gui.py @@ -780,7 +780,7 @@ def keyPressEvent(self, event): # when in stroke, allow escaping out of drawing else: - if event.key() == QtCore.Qt.Key_Escape: + if self.in_stroke and event.key() == QtCore.Qt.Key_Escape: self.layer.end_stroke(keep_stroke=False) if event.key() == QtCore.Qt.Key_Minus or event.key() == QtCore.Qt.Key_Equal: self.p0.keyPressEvent(event) From 4768c1836f226e7f43f33fc9f59ddd08ed49a348 Mon Sep 17 00:00:00 2001 From: Michael Rariden Date: Thu, 21 May 2026 15:50:35 -0400 Subject: [PATCH 3/6] remove unused imports, simplify & clarify changes, fix dtype bugs in SaturationSliderDialog --- cellpose/gui/gui.py | 16 +++++++--------- cellpose/gui/guiparts.py | 29 +++++++++++++++-------------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/cellpose/gui/gui.py b/cellpose/gui/gui.py index 35616bb6..00d13ef1 100644 --- a/cellpose/gui/gui.py +++ b/cellpose/gui/gui.py @@ -7,9 +7,9 @@ from qtpy import QtGui, QtCore from superqt import QCollapsible -from qtpy.QtWidgets import QScrollArea, QMainWindow, QApplication, QWidget, QScrollBar, \ +from qtpy.QtWidgets import QScrollArea, QMainWindow, QApplication, QWidget, \ QComboBox, QGridLayout, QPushButton, QFrame, QCheckBox, QLabel, QProgressBar, \ - QLineEdit, QMessageBox, QGroupBox, QMenu, QAction, QHBoxLayout + QLineEdit, QGroupBox import pyqtgraph as pg import numpy as np @@ -20,10 +20,9 @@ from . import guiparts, menus, io from .. import models, core, dynamics, version, train -from ..utils import download_url_to_file, masks_to_outlines, diameters -from ..io import get_image_files, imsave, imread +from ..utils import download_url_to_file +from ..io import get_image_files from ..transforms import resize_image, normalize99, normalize99_tile, smooth_sharpen_img -from ..models import normalize_default from ..plot import disk try: @@ -657,7 +656,6 @@ def open_slider_popup(self, r:int) -> None: high = int(high) dialog = SaturationSliderDialog(self, low=low, high=high) dialog.valueChanged.connect(lambda val, r=r: self.color_level_change(val, r)) - dialog.show() dialog.setWindowFlags(QtCore.Qt.Popup) # make it stationary and temporary dialog.show() @@ -683,9 +681,9 @@ def color_level_change(self, lohi:tuple, r:int) -> None: self.saturation[r][self.currentZ] = lohi # update all the layers if autobtn is unchecked if not self.autobtn.isChecked(): - for r in range(3): - for i in range(len(self.saturation[r])): - self.saturation[r][i] = self.saturation[r][self.currentZ] + for ch in range(3): + for i in range(len(self.saturation[ch])): + self.saturation[ch][i] = self.saturation[ch][self.currentZ] self.update_plot() diff --git a/cellpose/gui/guiparts.py b/cellpose/gui/guiparts.py index b0e9ae7a..8fcc30f7 100644 --- a/cellpose/gui/guiparts.py +++ b/cellpose/gui/guiparts.py @@ -891,24 +891,22 @@ def __init__(self, parent: QWidget, low:int|None=None, high:int|None=None, dtype except TypeError: raise TypeError(f"Expected valid numpy data type, got {type(dtype)}") - dtype_min = np.iinfo(dtype).min - dtype_max = np.iinfo(dtype).max + self.dtype_min = np.iinfo(dtype).min + self.dtype_max = np.iinfo(dtype).max - if not low: - low = dtype_min - if not high: - high = dtype_max + if low is None: + low = self.dtype_min + if high is None: + high = self.dtype_max self.slider = Slider(self) layout = QGridLayout(self) low_textbox = QLineEdit(self) low_textbox.setFixedWidth(50) - low_textbox.textChanged.connect(self._validate_update_low_textbox) self.low_textbox = low_textbox high_textbox = QLineEdit(self) high_textbox.setFixedWidth(50) - high_textbox.textChanged.connect(self._validate_update_high_textbox) self.high_textbox = high_textbox layout.addWidget(low_textbox, 0, 0) @@ -917,16 +915,19 @@ def __init__(self, parent: QWidget, low:int|None=None, high:int|None=None, dtype layout.setColumnStretch(1, 1) self.setLayout(layout) - self.slider.setMinimum(dtype_min) - self.slider.setMaximum(dtype_max) - self.slider.setValue([dtype_min, dtype_max]) + self.slider.setMinimum(self.dtype_min) + self.slider.setMaximum(self.dtype_max) + self.slider.setValue([self.dtype_min, self.dtype_max]) self.slider.setEnabled(True) - self.slider.valueChanged.connect(self.slider_changed) self._low = low self._high = high self.low_textbox.setText(str(low)) self.high_textbox.setText(str(high)) + + low_textbox.textChanged.connect(self._validate_update_low_textbox) + high_textbox.textChanged.connect(self._validate_update_high_textbox) + self.slider.valueChanged.connect(self.slider_changed) def _validate_text_input(self, value) -> int: @@ -990,8 +991,8 @@ def high(self, value:int) -> None: def _update_validators(self) -> None: """ Update the textbox validators after editing """ - self.high_textbox.setValidator(QtGui.QIntValidator(self.low, 255)) - self.low_textbox.setValidator(QtGui.QIntValidator(0, self.high)) + self.high_textbox.setValidator(QtGui.QIntValidator(self.low, self.dtype_max)) + self.low_textbox.setValidator(QtGui.QIntValidator(self.dtype_min, self.high)) def slider_changed(self, lohi) -> None: From efbde2e7688661167e3d7841dbcfc163b1c2e587 Mon Sep 17 00:00:00 2001 From: Michael Rariden Date: Thu, 21 May 2026 15:51:04 -0400 Subject: [PATCH 4/6] just use BaseSlider, typo fixes --- cellpose/gui/gui.py | 2 +- cellpose/gui/guiparts.py | 14 ++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/cellpose/gui/gui.py b/cellpose/gui/gui.py index 00d13ef1..d97bf018 100644 --- a/cellpose/gui/gui.py +++ b/cellpose/gui/gui.py @@ -670,7 +670,7 @@ def open_slider_popup(self, r:int) -> None: def color_level_change(self, lohi:tuple, r:int) -> None: - """ Set the saturation attribute for the color `r` to `lowhi` and + """ Set the saturation attribute for the color `r` to `lohi` and call self.update_plot(). Also, update all the layers if self.autobtn is unchecked. diff --git a/cellpose/gui/guiparts.py b/cellpose/gui/guiparts.py index 8fcc30f7..5b38727b 100644 --- a/cellpose/gui/guiparts.py +++ b/cellpose/gui/guiparts.py @@ -856,12 +856,6 @@ def __init__(self, parent): self.show() -class Slider(BaseSlider): - """ Simple slider """ - def __init__(self, parent): - super().__init__(parent) - - class SaturationSliderDialog(QDialog): """ Slider dialog with signal for reporting the slider changes @@ -871,7 +865,7 @@ class SaturationSliderDialog(QDialog): valueChanged = QtCore.Signal(tuple) - def __init__(self, parent: QWidget, low:int|None=None, high:int|None=None, dtype:str|np.dtype|None=None): + def __init__(self, parent: QWidget, low:int|None=None, high:int|None=None, dtype:np.dtype|None=None): """ Slider dialog with signal for report slider changes. After instantiation, hook up the `.valueChanged` to listen for events from this widget. @@ -883,7 +877,7 @@ def __init__(self, parent: QWidget, low:int|None=None, high:int|None=None, dtype """ super().__init__(parent) - if not dtype: + if dtype is None: dtype = np.dtype(np.uint8) try: @@ -899,7 +893,7 @@ def __init__(self, parent: QWidget, low:int|None=None, high:int|None=None, dtype if high is None: high = self.dtype_max - self.slider = Slider(self) + self.slider = BaseSlider(self) layout = QGridLayout(self) low_textbox = QLineEdit(self) low_textbox.setFixedWidth(50) @@ -996,7 +990,7 @@ def _update_validators(self) -> None: def slider_changed(self, lohi) -> None: - """ Set the low and high values and emit the valueChagned signal. """ + """ Set the low and high values and emit the valueChanged signal. """ lo, hi = lohi self.low = lo self.high = hi From fb26b2ad5a0f416b1210955edd108e7aa0c071a3 Mon Sep 17 00:00:00 2001 From: Michael Rariden Date: Thu, 21 May 2026 16:29:53 -0400 Subject: [PATCH 5/6] improve docstrings --- cellpose/gui/gui.py | 21 +++++++++++++-------- cellpose/gui/guiparts.py | 33 ++++++++++++++++----------------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/cellpose/gui/gui.py b/cellpose/gui/gui.py index d97bf018..16e2964a 100644 --- a/cellpose/gui/gui.py +++ b/cellpose/gui/gui.py @@ -644,11 +644,15 @@ def make_buttons(self): return b def open_slider_popup(self, r:int) -> None: - """ Open slider popup and attach it to the color index `r`. - Clicking off of the popup causes it to close. + """Open a saturation slider popup for the color channel at index ``r``. + + The popup closes when the user clicks outside of it. Args: - r (int): The index of the color slider (0, 1, 2). + r (int): Color channel index. + + Raises: + AssertionError: If ``r`` is not in {0, 1, 2}. """ assert r in [0, 1, 2], f'The color index, `r`, must be in (0, 1, 2), got {r}' low, high = self.saturation[r][self.currentZ] @@ -670,13 +674,14 @@ def open_slider_popup(self, r:int) -> None: def color_level_change(self, lohi:tuple, r:int) -> None: - """ Set the saturation attribute for the color `r` to `lohi` and - call self.update_plot(). Also, update all the layers if self.autobtn - is unchecked. + """Update the saturation range for color channel ``r`` and refresh the plot. + + If the auto-adjust button is unchecked, the same range is applied + to all z-layers for all channels. Args: - lohi (tuple): Tuple of (low, high) values for the saturation/slider. - r (int): The index of the color to adjust. + lohi (tuple[int, int]): (low, high) saturation values. + r (int): Color channel index. """ self.saturation[r][self.currentZ] = lohi # update all the layers if autobtn is unchecked diff --git a/cellpose/gui/guiparts.py b/cellpose/gui/guiparts.py index 5b38727b..462f1da1 100644 --- a/cellpose/gui/guiparts.py +++ b/cellpose/gui/guiparts.py @@ -842,9 +842,7 @@ def setDrawKernel(self, kernel_size=3): class BaseSlider(QRangeSlider): - """ Base slider with style sheet definition and horizontal orientation - - Relies on built-in `.valueChanged()` method""" + """Horizontal range slider. Starts disabled.""" def __init__(self, parent): super().__init__(Horizontal) self.setParent(parent) @@ -857,24 +855,25 @@ def __init__(self, parent): class SaturationSliderDialog(QDialog): - """ Slider dialog with signal for reporting the slider changes + """A range slider dialog with text box inputs for fine-grained control. - Internally, the textboxes listen to and update the slider values, and - only the slider values are used in the valueChanged interface. + Connect to ``valueChanged`` to receive ``(low, high)`` tuples whenever the + slider or text boxes change. """ + # Note: The textboxes update the slider and only the slider is connected to signals. + # This way, only the ``valueChanged`` signal is required for all syncing. + valueChanged = QtCore.Signal(tuple) def __init__(self, parent: QWidget, low:int|None=None, high:int|None=None, dtype:np.dtype|None=None): - """ Slider dialog with signal for report slider changes. After instantiation, - hook up the `.valueChanged` to listen for events from this widget. - + """ Args: - parent (QWidget): A Qt widget from which this object can be referenced. - low (int | None, optional): The low value to initialize the slider. Defaults to dtype.min. - high (int | None, optional): The high value to initialize the slider. Defaults to dtype.max. - dtype (np.dtype | None, optional): . Defaults to np.uint8. - """ + parent (QWidget): Parent widget. + low (int | None, optional): Initial low value. Defaults to ``dtype`` minimum. + high (int | None, optional): Initial high value. Defaults to ``dtype`` maximum. + dtype (np.dtype | None, optional): Data type used to set slider bounds. Defaults to ``np.uint8``. + """ super().__init__(parent) if dtype is None: @@ -925,14 +924,14 @@ def __init__(self, parent: QWidget, low:int|None=None, high:int|None=None, dtype def _validate_text_input(self, value) -> int: - """ Convert textbox input into ``int`` """ + """Convert textbox string to ``int``, returning 0 for empty input.""" if len(value) < 1: value = 0 return int(value) def _validate_update_low_textbox(self) -> None: - """ Validate textbox input and set slider low value """ + """Read the low textbox and update the slider; no-op if low would exceed high.""" low = self._validate_text_input(self.low_textbox.text()) high = self.slider.value()[1] if low <= high: @@ -940,7 +939,7 @@ def _validate_update_low_textbox(self) -> None: def _validate_update_high_textbox(self) -> None: - """ Validate textbox input and set slider high value """ + """Read the high textbox and update the slider; no-op if high would go below low.""" low = self.slider.value()[0] high = self._validate_text_input(self.high_textbox.text()) if low <= high: From dc6355e6153c6b8918c9a3a1e7b781104cbcd816 Mon Sep 17 00:00:00 2001 From: Michael Rariden Date: Thu, 21 May 2026 16:48:30 -0400 Subject: [PATCH 6/6] make popup setting internal, fix slider low/high bug --- cellpose/gui/gui.py | 1 - cellpose/gui/guiparts.py | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cellpose/gui/gui.py b/cellpose/gui/gui.py index 16e2964a..1f171e74 100644 --- a/cellpose/gui/gui.py +++ b/cellpose/gui/gui.py @@ -660,7 +660,6 @@ def open_slider_popup(self, r:int) -> None: high = int(high) dialog = SaturationSliderDialog(self, low=low, high=high) dialog.valueChanged.connect(lambda val, r=r: self.color_level_change(val, r)) - dialog.setWindowFlags(QtCore.Qt.Popup) # make it stationary and temporary dialog.show() # move the dialog to the top of the window: diff --git a/cellpose/gui/guiparts.py b/cellpose/gui/guiparts.py index 462f1da1..25c6467a 100644 --- a/cellpose/gui/guiparts.py +++ b/cellpose/gui/guiparts.py @@ -910,7 +910,7 @@ def __init__(self, parent: QWidget, low:int|None=None, high:int|None=None, dtype self.slider.setMinimum(self.dtype_min) self.slider.setMaximum(self.dtype_max) - self.slider.setValue([self.dtype_min, self.dtype_max]) + self.slider.setValue([low, high]) self.slider.setEnabled(True) self._low = low @@ -918,6 +918,7 @@ def __init__(self, parent: QWidget, low:int|None=None, high:int|None=None, dtype self.low_textbox.setText(str(low)) self.high_textbox.setText(str(high)) + self.setWindowFlags(QtCore.Qt.Popup) # make it stationary and temporary low_textbox.textChanged.connect(self._validate_update_low_textbox) high_textbox.textChanged.connect(self._validate_update_high_textbox) self.slider.valueChanged.connect(self.slider_changed)