Qt double spin box autofills when processing value changed

Viewed 810

I have a time-consuming computation that depends on a double value. For this, I've created a GUI where I can set the value for the computation using a QDoubleSpinBox. The double spin box QDoubleSpinBox::valueChanged(double) signal is connected to a slot that starts the heavy computation in a new thread using QtConcurrent::run. The problem is that when I add a progress bar, the double spin box automatically fills its contents (zero-padding until the number of decimals) when the progress bar appears. My feeling is that this is because the double spin box loses the focus (i.e. the progress bar is the selected widget).

My question is:

  • How can I show the progress bar and make the double spin box not fill the rest of the decimals with zeros?

This video shows how, when the progress bar is not shown, I can keep editing the double spin box while, when the progress bar is shown, the double spin box fills its precision with zeros. This is the current behavior, not the desired one. The desired one is that after the computation is done the double spin box is has not automatically filled its empty decimal places with zeros. Here is the code used for the video (fully available in GitHub):

Header

class DoubleSpinboxHeavyComputation : public QWidget
{
  Q_OBJECT

public:
  explicit DoubleSpinboxHeavyComputation(QWidget *parent = nullptr);
  ~DoubleSpinboxHeavyComputation();

signals:

  void computationDone();

  void progressSignal(int progress_state);

private slots:
  void startHeavyComputationInThread();

  void heavyComputation();

private:
  Ui::DoubleSpinboxHeavyComputation *ui;
  int n_ = 0;
};

Implementation

DoubleSpinboxHeavyComputation::DoubleSpinboxHeavyComputation(QWidget *parent)
  : QWidget(parent), ui(new Ui::DoubleSpinboxHeavyComputation)
{
  ui->setupUi(this);
  connect(ui->doubleSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
          &DoubleSpinboxHeavyComputation::startHeavyComputationInThread);
}

DoubleSpinboxHeavyComputation::~DoubleSpinboxHeavyComputation()
{
  delete ui;
}

void DoubleSpinboxHeavyComputation::startHeavyComputationInThread()
{
  if (ui->checkBox->isChecked())
  {
    QProgressDialog *progress = new QProgressDialog("Computing", "", 0, 0, this);
    progress->setWindowTitle(windowTitle());
    progress->setWindowFlags((progress->windowFlags() | Qt::CustomizeWindowHint) &
                             ~Qt::WindowCloseButtonHint);  // Hide close button
    progress->setWindowModality(Qt::WindowModal);
    progress->setCancelButton(nullptr);
    progress->setMaximum(1000);
    progress->show();
    connect(this, &DoubleSpinboxHeavyComputation::progressSignal, progress, &QProgressDialog::setValue);
    connect(this, &DoubleSpinboxHeavyComputation::computationDone, progress, &QProgressDialog::close);
    connect(this, &DoubleSpinboxHeavyComputation::computationDone, progress, &QProgressDialog::deleteLater);
  }
  QtConcurrent::run(this, &DoubleSpinboxHeavyComputation::heavyComputation);
}

void DoubleSpinboxHeavyComputation::heavyComputation()
{
  int current_n = n_;
  ++n_;
  qDebug() << "Start computation " << current_n;
  for (int i = 0; i < 1000; i++)
  {
    emit progressSignal(i);
    usleep(1000);
  }
  qDebug() << "End computation" << current_n;
  emit computationDone();
}
1 Answers

Looks like you need to subclass your QDoubleSpinbox and reimplement textFromValue method

class NumericEdit : public QDoubleSpinBox
{
    Q_OBJECT
public:
    NumericEdit(QWidget *p_parent = nullptr);

    QString textFromValue(double val) const;

};

QString NumericEdit::textFromValue(double val) const
{
    //default converting
//    return QString::number(val);
    //converting with a local representation
    QLocale locale;
    return locale.toString(val);
}

But this will break default prefix and suffix functional of spinbox

Related