Skip to content

Instantly share code, notes, and snippets.

@jdreaver
Last active March 2, 2023 19:45
Show Gist options
  • Save jdreaver/0be2e44981159d0854f5 to your computer and use it in GitHub Desktop.
Save jdreaver/0be2e44981159d0854f5 to your computer and use it in GitHub Desktop.
A Scientific Notation Double Spin Box for PyQt/PySide
# Regular expression to find floats. Match groups are the whole string, the
# whole coefficient, the decimal part of the coefficient, and the exponent
# part.
_float_re = re.compile(r'(([+-]?\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?)')
def valid_float_string(string):
match = _float_re.search(string)
return match.groups()[0] == string if match else False
class FloatValidator(QtGui.QValidator):
def validate(self, string, position):
if valid_float_string(string):
return self.State.Acceptable
if string == "" or string[position-1] in 'e.-+':
return self.State.Intermediate
return self.State.Invalid
def fixup(self, text):
match = _float_re.search(text)
return match.groups()[0] if match else ""
class ScientificDoubleSpinBox(QtGui.QDoubleSpinBox):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setMinimum(-np.inf)
self.setMaximum(np.inf)
self.validator = FloatValidator()
self.setDecimals(1000)
def validate(self, text, position):
return self.validator.validate(text, position)
def fixup(self, text):
return self.validator.fixup(text)
def valueFromText(self, text):
return float(text)
def textFromValue(self, value):
return format_float(value)
def stepBy(self, steps):
text = self.cleanText()
groups = _float_re.search(text).groups()
decimal = float(groups[1])
decimal += steps
new_string = "{:g}".format(decimal) + (groups[3] if groups[3] else "")
self.lineEdit().setText(new_string)
def format_float(value):
"""Modified form of the 'g' format specifier."""
string = "{:g}".format(value).replace("e+", "e")
string = re.sub("e(-?)0*(\d+)", r"e\1\2", string)
return string
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment