From d461bf866f3abd53484e6334e7bc69e7c36470aa Mon Sep 17 00:00:00 2001 From: dlidstrom Date: Mon, 16 Mar 2015 15:30:15 -0600 Subject: [PATCH 1/2] Add wrapping option to SpinBox --- pyqtgraph/widgets/SpinBox.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/pyqtgraph/widgets/SpinBox.py b/pyqtgraph/widgets/SpinBox.py index a863cd60..7c3fe256 100644 --- a/pyqtgraph/widgets/SpinBox.py +++ b/pyqtgraph/widgets/SpinBox.py @@ -51,6 +51,7 @@ class SpinBox(QtGui.QAbstractSpinBox): value (float/int) initial value. Default is 0.0. bounds (min,max) Minimum and maximum values allowed in the SpinBox. Either may be None to leave the value unbounded. By default, values are unbounded. + wrapping (bool) If True and both bounds are not None, spin box has circular behavior. suffix (str) suffix (units) to display after the numerical value. By default, suffix is an empty str. siPrefix (bool) If True, then an SI prefix is automatically prepended to the units and the value is scaled accordingly. For example, @@ -81,6 +82,7 @@ class SpinBox(QtGui.QAbstractSpinBox): self.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred) self.opts = { 'bounds': [None, None], + 'wrapping': False, ## Log scaling options #### Log mode is no longer supported. #'step': 0.1, @@ -205,6 +207,14 @@ class SpinBox(QtGui.QAbstractSpinBox): self.opts['bounds'][0] = m if update: self.setValue() + + def wrapping(self): + """Return whether or not the spin box is circular.""" + return self.opts['wrapping'] + + def setWrapping(self, s): + """Set whether spin box is circular. Both bounds must be set for this to have an effect.""" + self.opts['wrapping'] = s def setPrefix(self, p): """Set a string prefix. @@ -282,10 +292,17 @@ class SpinBox(QtGui.QAbstractSpinBox): value = self.value() bounds = self.opts['bounds'] - if bounds[0] is not None and value < bounds[0]: - value = bounds[0] - if bounds[1] is not None and value > bounds[1]: - value = bounds[1] + + if bounds[0] is not None and bounds[1] is not None and self.opts['wrapping']: + # Casting of Decimals to floats required to avoid unexpected behavior of remainder operator + value = float(value) + l, u = float(bounds[0]), float(bounds[1]) + value = (value - l) % (u - l) + l + else: + if bounds[0] is not None and value < bounds[0]: + value = bounds[0] + if bounds[1] is not None and value > bounds[1]: + value = bounds[1] if self.opts['int']: value = int(value) From 92d8c2630b096cea2a214c685eb36c2412b3f653 Mon Sep 17 00:00:00 2001 From: lidstrom83 Date: Sun, 25 Oct 2015 03:55:37 -0600 Subject: [PATCH 2/2] Add spin box wrapping example. --- examples/SpinBox.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/SpinBox.py b/examples/SpinBox.py index 2fa9b161..268bfa72 100644 --- a/examples/SpinBox.py +++ b/examples/SpinBox.py @@ -31,6 +31,8 @@ spins = [ pg.SpinBox(value=1.0, suffix='V', siPrefix=True, dec=True, step=0.5, minStep=0.01)), ("Float with SI-prefixed units,
dec step=1.0, minStep=0.001", pg.SpinBox(value=1.0, suffix='V', siPrefix=True, dec=True, step=1.0, minStep=0.001)), + ("Integer with bounds=[10, 20] and wrapping", + pg.SpinBox(value=10, bounds=[10, 20], int=False, minStep=1, step=1, wrapping=True)), ]