QDoubleSpinbox with editable unit (suffix)

79 Views Asked by At

I am trying to make a QDoubleSpinbox that allows for entering custom metric distances with units, e.g. "3.123 mm", "2.1 um", "10.567 m".

Is there any way to convince QDoubleSpinbox to make the suffix editable?

1

There are 1 best solutions below

6
knipknap On BEST ANSWER

I figured it out. Can't use suffix(), but there is another way. Here you go:

import re
from PySide.QtGui import QApplication, QDoubleSpinBox, QValidator, QAbstractSpinBox

_value_split_re = re.compile(r'^([\d\.]+)\s*(\S*)$')
def _parse_value(value):
    if not isinstance(value, str):
        return value, None
    value, unit = _value_split_re.match(value).groups()
    return float(value), unit

class DistanceSpinBox(QDoubleSpinBox):
    def __init__(self, unit, allowed_units, parent=None):
        self.unit = unit
        self.allowed_units = allowed_units
        super().__init__(parent)
        self.setStepType(QAbstractSpinBox.AdaptiveDecimalStepType)
        #self.setKeyboardTracking(False)

    def textFromValue(self, value):
        decimals = self.decimals()
        fmt = f"{{:.{decimals}f}} {self.unit}"
        return fmt.format(value)

    def valueFromText(self, text):
        try:
            value, unit = _parse_value(text)
        except AttributeError:
            return .0

        if unit in self.allowed_units:
            self.unit = unit
            self.valueChanged.emit(value)

        return value

    def validate(self, text, pos):
        return QValidator.Acceptable, text, pos

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    spin_box = DistanceSpinBox('mm', ('nm', 'mm', 'cm', 'in', 'ft'))
    spin_box.show()
    sys.exit(app.exec_())

Alternatively, here is a link to the full version that includes some checks.