2

I have tried searching for this problem in various ways, but have found nothing relevant, so perhaps there is a simple way around this which I simply haven't found. If so, my apologies in advance.

I am using a number of QSpinBoxes in my app, and they have a behaviour which I find quite frustrating, namely that if you insert the cursor and try to type, it is blocked and nothing is inserted. If I then delete a character, then I can type one character, and so on.

Example:

Spinbox shows: 0.0000

I insert the cursor after the '.' and want to type '5', i.e. it would then have 0.50000. This is blocked, since the spinbox is full, given the constraints I have set on limits and precision. I have to press Delete to remove one '0', so it says 0.000 and then I can type my '5'.

How can I let the spinbox accept all valid input while typing, and only worry about truncating the value at the end?

2 Answers2

0

You could probably subclass the QDoubleSpinBox and re-implement its validate method to allow numbers with more decimal points.

Then capture the editingFinished signal to truncate the entered value.

Todd
  • 90
  • 6
  • Yes, that may be what I will end up having to do, but I was hoping that I had simply missed some capability, since the native controls of the major platforms all operate like that, AFAIK. It is odd that Qt chose to do it so differently, without providing a control for getting the "usual" behaviour. – Carsten Whimster Feb 27 '15 at 09:26
0

As mentioned in other question I think there is only one way of doing this by overriding QDoubleSpinBox::validate class.

Example implementation:

QValidator::State DoubleSpinBox::validate(QString& input, int& pos) const
{
    //support prefix & suffix
    const int decimalPointIndex = input.indexOf(locale().decimalPoint());
    if(decimalPointIndex != -1 && decimalPointIndex < pos)
    {
        //Find last not digit
        const auto lastNotDigitIt =
            std::find_if_not(input.begin() + decimalPointIndex + 1,
                             input.end(),
                             [](const auto& item) { return item.isDigit(); });
        const int lastNotDigitIndex = std::distance(input.begin(), lastNotDigitIt);

        //Check should we trim input to desired decimals
        const int extraDigits = (lastNotDigitIndex - 1 - decimalPointIndex) - decimals();
        if(extraDigits > 0 && lastNotDigitIndex != decimalPointIndex)
        {
            QString copy = input;
            //trim
            input.erase(lastNotDigitIt - extraDigits, lastNotDigitIt);
        }
    }
    return QDoubleSpinBox::validate(input, pos);
}

If you need to use such class in Designer tool you need to just promote your widget. (Pretty easy)

Gelldur
  • 11,187
  • 7
  • 57
  • 68