I am trying to find a way to put negative numbers in a QDoubleSpinBox
. I read the documentation but haven't found the solution yet. Here is the class I made to customize my QDoubleSpinBox
:
class ComboBoxDelegate(QStyledItemDelegate):
"""A delegate that allows the user to change integer values from the model
using a spin box widget. """
def __init__(self, parent=None):
super().__init__(parent)
def createEditor(self, parent, option, index : QModelIndex):
if index.column() == 0 :
editor = QLineEdit(parent)
return editor
if index.column() == 1 :
combo = QComboBox(parent)
combo.addItems(["len","diam","conc"])
editor = combo
return editor
if index.column() > 1 :
editor = CustomDoubleSpinbox(parent)
editor.setDecimals(3)
return editor
def setEditorData(self, editor , index):
value = index.model().data(index, Qt.EditRole)
if type(editor) == QComboBox :
editor.setCurrentText(str(value))
if type(editor) == CustomDoubleSpinbox :
editor.setValue(value)
if type(editor) == QLineEdit :
editor.setText(value)
def setModelData(self, editor , model, index : QModelIndex):
if type(editor) == QComboBox :
value = editor.currentText()
if type(editor) == CustomDoubleSpinbox :
editor.interpretText()
value = editor.value()
if type(editor) == QLineEdit :
value = editor.text()
model.setData(index, value, Qt.EditRole)
def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect)
class CustomDoubleSpinbox(QDoubleSpinBox):
def validate(self, text: str, pos: int) -> object:
text = text.replace(".", ",")
return QDoubleSpinBox.validate(self, text, pos)
def valueFromText(self, text: str) -> float:
text = text.replace(",", ".")
return float(text)
EDIT
h4z3 found the solution in the documentation : QDoubleSpinBox for python. By setting a negative minimum with the setMinimum
method, it works.
Constructs a spin box with 0.0 as minimum value and 99.99 as maximum value, a step value of 1.0 and a precision of 2 decimal places.
But just below there's:
See also setMinimum() setMaximum() setSingleStep()
So since you're inheriting from QDoubleSpinBox, it would be the best to modify this in init:
class CustomDoubleSpinbox(QDoubleSpinBox):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # to not break inheritance
self.setMinimum(-99.99) # we inherited the method, so we can now set our own minimum to be used
def validate(self, text: str, pos: int) -> object:
text = text.replace(".", ",")
return QDoubleSpinBox.validate(self, text, pos)
def valueFromText(self, text: str) -> float:
text = text.replace(",", ".")
return float(text)
This way, every time you create the object of CustomDoubleSpinbox class, the minimum will be always changed - as opposed to using setMinimum somewhere else in the code.
The *args and **kwargs are a way to ensure the code doesn't break if signature changes. In this case, QDoubleSpinBox only takes optional parent and we could just hardcode it. But I like pretty and flexible code. (You can switch those two lines to def __init__(self, parent=None):
and super().__init__(parent)
- it will be the same. Just remember that setting min needs to be after the super, not before.)
You could also use setRange to be explicit about both min and max (because max is now not obvious without reading docs).
I also used -99.99 in setMinimum to match default max of 99.99 - but of course you might want to adjust that value as well.