Question

I need QSpinBox for unsigned int. Therefore I have wrote simple class:

class UnsignedSpinBox : public QAbstractSpinBox {
private:
  uint32_t value = 0;
  uint32_t minimum = 0;
  uint32_t maximum = 100;
private:
  void stepBy(int steps) {
    if (steps < 0 && (uint32_t)(-1 * steps) > value - minimum)
      value = minimum;
    else if (steps > 0 && maximum - value < (uint32_t)steps)
      value = maximum;
    else
      value += steps;
    lineEdit()->setText(QString::number(value));
  }
  StepEnabled stepEnabled() const {
    if (value < maximum && value > minimum)
      return QAbstractSpinBox::StepUpEnabled | QAbstractSpinBox::StepDownEnabled;
    else if (value < maximum)
      return QAbstractSpinBox::StepUpEnabled;
    else if (value > minimum)
      return QAbstractSpinBox::StepDownEnabled;
    else
      return QAbstractSpinBox::StepNone;
  }
  QValidator::State validate(QString &input, int &) const {
    if (input.isEmpty())
      return QValidator::Intermediate;
    bool ok = false;
    uint32_t validateValue = input.toUInt(&ok);
    if (!ok || validateValue > maximum || validateValue < minimum)
      return QValidator::Invalid;
    else
      return QValidator::Acceptable;
  }

public:
  UnsignedSpinBox(QWidget* parent = 0) : QAbstractSpinBox(parent) {
    lineEdit()->setText(QString::number(value));
  }
  virtual ~UnsignedSpinBox() { }
};

In gerenal it works fine but it has one shortcoming. Step buttons are refreshed only after mouse moving (althouth function stepEnabled is called every second). As a result if I hold Page Up, my spin box gets maximum value and these step buttons don't change their state until I move my mouse. Or if value is 0, one pressing of Page Up or up arrow key on a keyboard changes value and text, but doesn't change buttons' state (down button is still disabled). Moreover, when value == maximum both buttons are disabled although function stepEnabled returnes QAbstractSpinBox::StepDownEnabled (I've checked it). What am I doing wrong? How can I enforce QAbstractSpinBox to draw these buttons correctly?

P.S. I use Debian. But I don't think it does matter since QSpinBox works fine

Was it helpful?

Solution

I think the Qt on your platform is either too old or otherwise broken. It works fine on OS X, on both Qt 4.8.5 and Qt 5.2.0.

There are two other solutions:

  1. If you don't care about full range of unsigned integer, simply use QSpinBox and set non-negative minimum and maximum. That's all. On platforms with 32 bit int, maximum int value is 2^31-1, that's about half of the maximum uint value of 2^32-1.

  2. You can use QDoubleSpinBox. On sane platforms you care about, double has more than 32 bits of mantissa, so you can convert it to a quint32 without loss of precision.

    If you want to be sure, just add static_assert(sizeof(double)>4) anywhere in your code.

    If one worries about performance, then it really doesn't matter. The calculations are performed at the rate of user input events: that's a couple dozen double operations per second. It doesn't matter.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top