Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tracking property to sliders. When False, changed only emits on release. #248

Merged
merged 2 commits into from
Jul 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/log_slider.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
@magicgui(
auto_call=True,
result_widget=True,
input={"widget_type": "LogSlider", "max": 10000, "min": 1},
input={"widget_type": "LogSlider", "max": 10000, "min": 1, "tracking": False},
)
def slider(input=1):
return round(input, 4)
Expand Down
11 changes: 11 additions & 0 deletions magicgui/backends/_qtpy/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,17 @@ def _mgui_get_orientation(self) -> Any:
def _mgui_set_readout_visibility(self, value: bool):
raise NotImplementedError()

def _mgui_get_tracking(self) -> bool:
# Progressbar also uses this base, but doesn't have tracking
if hasattr(self._qwidget, "hasTracking"):
return self._qwidget.hasTracking()
return False

def _mgui_set_tracking(self, value: bool) -> None:
# Progressbar also uses this base, but doesn't have tracking
if hasattr(self._qwidget, "setTracking"):
self._qwidget.setTracking(value)


class Slider(_Slider):
_qwidget: QtW.QSlider
Expand Down
21 changes: 20 additions & 1 deletion magicgui/widgets/_bases/slider_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,29 @@ class SliderWidget(RangedWidget, _OrientationMixin):

_widget: _protocols.SliderWidgetProtocol

def __init__(self, orientation: str = "horizontal", readout=True, **kwargs):
def __init__(
self, orientation: str = "horizontal", readout=True, tracking=True, **kwargs
):
kwargs["backend_kwargs"] = {"readout": readout, "orientation": orientation}
self._readout = readout
super().__init__(**kwargs)
self.tracking = tracking

@property
def tracking(self) -> bool:
"""Return whether slider tracking is enabled.

If tracking is enabled (the default), the slider emits the changed()
signal while the slider is being dragged. If tracking is disabled,
the slider emits the valueChanged() signal only when the user releases
the slider.
"""
return self._widget._mgui_get_tracking()

@tracking.setter
def tracking(self, value: bool) -> None:
"""Set whether slider tracking is enabled."""
self._widget._mgui_set_tracking(value)

@property
def options(self) -> dict:
Expand Down
27 changes: 26 additions & 1 deletion magicgui/widgets/_concrete.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

from magicgui.application import use_app
from magicgui.types import FileDialogMode, PathLike
from magicgui.widgets import _protocols
from magicgui.widgets._bases.mixins import _OrientationMixin, _ReadOnlyMixin

from ._bases import (
Expand Down Expand Up @@ -304,8 +305,15 @@ class LogSlider(TransformedRangedWidget):
The base to use for the log, by default math.e.
"""

_widget: _protocols.SliderWidgetProtocol

def __init__(
self, min: float = 1, max: float = 100, base: float = math.e, **kwargs
self,
min: float = 1,
max: float = 100,
base: float = math.e,
tracking=True,
**kwargs,
):
for key in ("maximum", "minimum"):
if key in kwargs:
Expand All @@ -329,6 +337,23 @@ def __init__(
widget_type=app.get_obj("Slider"),
**kwargs,
)
self.tracking = tracking

@property
def tracking(self) -> bool:
"""Return whether slider tracking is enabled.

If tracking is enabled (the default), the slider emits the changed()
signal while the slider is being dragged. If tracking is disabled,
the slider emits the valueChanged() signal only when the user releases
the slider.
"""
return self._widget._mgui_get_tracking()

@tracking.setter
def tracking(self, value: bool) -> None:
"""Set whether slider tracking is enabled."""
self._widget._mgui_set_tracking(value)

@property
def _scale(self):
Expand Down
6 changes: 6 additions & 0 deletions magicgui/widgets/_protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,12 @@ class SliderWidgetProtocol(RangedWidgetProtocol, SupportsOrientation, Protocol):
def _mgui_set_readout_visibility(self, visible: bool) -> None:
"""Set visibility of readout widget."""

def _mgui_get_tracking(self) -> bool:
"""If tracking is False, valueChanged is only emitted when released."""

def _mgui_set_tracking(self, tracking: bool) -> None:
"""If tracking is False, valueChanged is only emitted when released."""


# CONTAINER ----------------------------------------------------------------------

Expand Down
7 changes: 7 additions & 0 deletions tests/test_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -614,3 +614,10 @@ def test_container_removal():
c.pop()
assert len(c) == 0
assert c.native.layout().count() == 0


def test_tracking():
slider = widgets.Slider(tracking=False)
assert slider.tracking is False
slider.tracking = True
assert slider.tracking