如何删除 Qt 中 QDoubleSpinBox 的 setfill('0') 特征?

Bil*_*Bob 5 c++ qt

看来 Qt 默认情况下将输入数字的精度设置为小数点后两位。如果小数 = 2 并且用户输入数字(例如 4),则会向用户显示 4.00。它是否可以只显示 4,但可以选择让用户将其编辑到小数点后两位并相应地显示更新的值?

Sch*_*eff 6

我编写的第一个示例代码旨在“接触”问题:

#include <QtWidgets>

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // setup GUI
  QDoubleSpinBox qEdit;
  qEdit.show();
  // install signal handler
  QObject::connect(&qEdit,
    (void (QDoubleSpinBox::*)(double))&QDoubleSpinBox::valueChanged,
    [&](double value){ qDebug() << "qEdit.value:" << qEdit.value(); });
  // run application
  return app.exec();
}
Run Code Online (Sandbox Code Playgroud)

我没想到的是(尽管这是合理的):您不能输入比配置更多的十进制数字。

另一种行为是:您可以输入任意数量的十进制数字。输入被完全解析和考虑(以便在内部以全精度存储值)。输出仅限于配置的数字,但只要您不再次编辑它,隐藏的小数仍然有效。

QDoubleSpinBox可以通过创建派生类DoubleSpinBox并重载相应的方法来更改其行为。

这些方法之一是
virtual QValidator::State validate(QString &text, int &pos) const override
作为Qt。文档。对实现这一点没有多大帮助我查看了woboq.org 上的类的源代码:QDoubleSpinBox

QValidator::State QDoubleSpinBox::validate(QString &text, int &pos) const
{
    Q_D(const QDoubleSpinBox);
    QValidator::State state;
    d->validateAndInterpret(text, pos, state);
    return state;
}
Run Code Online (Sandbox Code Playgroud)

因此,实际工作是由QDoubleSpinBoxPrivate::validateAndInterpret()(在撰写本文时)148 行代码完成的——繁重的东西。

为了提供概念证明,我决定将其变得更短并且不太完美:

QValidator::State DoubleSpinBox::validate(QString &text, int&) const
{
  bool ok = false;
  locale().toDouble(text, &ok);
  return ok ? QValidator::Acceptable : QValidator::Invalid;
}
Run Code Online (Sandbox Code Playgroud)

再次编译和测试表明值现在已被接受。现在,可以输入例如4.1234。键入此内容时,输出为:

#include <QtWidgets>

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // setup GUI
  QDoubleSpinBox qEdit;
  qEdit.show();
  // install signal handler
  QObject::connect(&qEdit,
    (void (QDoubleSpinBox::*)(double))&QDoubleSpinBox::valueChanged,
    [&](double value){ qDebug() << "qEdit.value:" << qEdit.value(); });
  // run application
  return app.exec();
}
Run Code Online (Sandbox Code Playgroud)

因此,这些值已被接受,但尚未在内部存储。 为了实现这一点,还必须重载该方法:
virtual double valueFromText(const QString &text) const

double DoubleSpinBox::valueFromText(const QString &text) const
{
  bool ok = false;
  double value = locale().toDouble(text, &ok);
  return ok ? value : QDoubleSpinBox::value();
}
Run Code Online (Sandbox Code Playgroud)

再次编译和测试表明,输入4.1234现在已被接受存储。输出是:

QValidator::State QDoubleSpinBox::validate(QString &text, int &pos) const
{
    Q_D(const QDoubleSpinBox);
    QValidator::State state;
    d->validateAndInterpret(text, pos, state);
    return state;
}
Run Code Online (Sandbox Code Playgroud)

当我按下向上箭头按钮时,显示变为5.12。但是,内部值仍然具有完整的精度,如输出中所示:

QValidator::State DoubleSpinBox::validate(QString &text, int&) const
{
  bool ok = false;
  locale().toDouble(text, &ok);
  return ok ? QValidator::Acceptable : QValidator::Invalid;
}
Run Code Online (Sandbox Code Playgroud)

完整的示例代码testQDoubleSpinBox.cc

#include <QtWidgets>

// a class for a customized QDoubleSpinBox
class DoubleSpinBox: public QDoubleSpinBox {
  public:
    // constructor.
    explicit DoubleSpinBox(QWidget *pQParent = nullptr):
      QDoubleSpinBox(pQParent)
    { }
    // destructor.
    virtual ~DoubleSpinBox() = default;
    // disabled:
    DoubleSpinBox(const DoubleSpinBox&) = delete;
    DoubleSpinBox& operator=(const DoubleSpinBox&) = delete;

  public:
    /* converts value from text.
     *
     * Overloaded to process accepted input correctly.
     */
    virtual double valueFromText(const QString &text) const override;

  protected:

    /* determines whether input is valid.
     *
     * Overloaded to change accepted input.
     */
    virtual QValidator::State validate(QString &text, int &pos) const override;

};

QValidator::State DoubleSpinBox::validate(QString &text, int&) const
{
  bool ok = false;
  locale().toDouble(text, &ok);
  return ok ? QValidator::Acceptable : QValidator::Invalid;
}

double DoubleSpinBox::valueFromText(const QString &text) const
{
  bool ok = false;
  double value = locale().toDouble(text, &ok);
  return ok ? value : QDoubleSpinBox::value();
}

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // setup GUI
  DoubleSpinBox qEdit;
  qEdit.show();
  // install signal handlers
  QObject::connect(&qEdit,
    (void (QDoubleSpinBox::*)(double))&QDoubleSpinBox::valueChanged,
    [&](double){ qDebug() << "qEdit.value:" << qEdit.value(); });
  // run application
  return app.exec();
}
Run Code Online (Sandbox Code Playgroud)

Qt 项目文件testQDoubleSpinBox.pro

4
4.1
4.12
0
Run Code Online (Sandbox Code Playgroud)

Windows 10 上cygwin中的示例会话:

double DoubleSpinBox::valueFromText(const QString &text) const
{
  bool ok = false;
  double value = locale().toDouble(text, &ok);
  return ok ? value : QDoubleSpinBox::value();
}
Run Code Online (Sandbox Code Playgroud)

testQDoubleSpinBox 的快照


Fel*_*lix 4

是的你可以。QDoubleSpinBox但你需要重新实现。

通过创建扩展旋转框的自定义类,您可以覆盖QDoubleSpinBox::textFromValue. 顾名思义,该方法用于将双精度数转换为字符串表示形式。

可能的实施:

QString MyDoubleSpinBox::textFromValue(double value) const
{
    return QLocale().toString(value, 'g', QLocale::FloatingPointShortest);
}
Run Code Online (Sandbox Code Playgroud)