如何在Qt中去除QDoubleSpinBox的setfill('0')特性?

5

似乎Qt默认将输入数字的精度设置为2位小数。如果小数=2,用户输入例如4的数字,则向用户显示4.00。是否可以仅显示4但允许用户编辑它并且相应更新值的选项?

2个回答

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();
}

我没有预料到的是(虽然这是合理的):您不能输入比配置更多的小数位。
另一种行为应该是:您可以输入任意数量的小数位。输入将被解析并完全考虑(因此在内部,该值以完全精度存储)。输出限制为已配置的小数位数,但只要您不再次编辑它,隐藏的小数位仍然处于活动状态。 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;
}

因此,实际工作是由QDoubleSpinBoxPrivate :: validateAndInterpret()完成的,该函数(在撰写本文时)有148行代码 - 非常复杂。

为了提供概念证明,我决定将其缩短并使其不那么完美:

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

编译和测试后显示数值现在被接受。现在,可以输入例如4.1234。在输入时,输出为:
4
4.1
4.12
0

因此,这些值被接受但尚未在内部存储。为了实现这一点,必须重载方法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();
}

编译和测试后发现输入 4.1234 现在被接受并存储。输出为:
4
4.1
4.12
4.123
4.1234

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

完整的示例代码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();
}

Qt项目文件 testQDoubleSpinBox.pro

SOURCES = testQDoubleSpinBox.cc

QT += widgets

在 Windows 10 上使用 cygwin 的示例会话:

$ qmake-qt5 testQDoubleSpinBox.pro

$ make
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQDoubleSpinBox.o testQDoubleSpinBox.cc
g++  -o testQDoubleSpinBox.exe testQDoubleSpinBox.o   -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread 

$ ./testQDoubleSpinBox 
Qt Version: 5.9.2
qEdit.value: 4
qEdit.value: 4.1
qEdit.value: 4.12
qEdit.value: 4.123
qEdit.value: 4.1234
qEdit.value: 5.1234

snapshot of testQDoubleSpinBox


4

是的,你可以。不过你需要重新实现QDoubleSpinBox

通过创建一个自定义类,并继承该spinbox,你可以重写QDoubleSpinBox::textFromValue方法。正如其名称所示,此方法用于将double类型转换为字符串表示形式。

可能的实现方式:

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

@Scheff 建设性的评论! - Mohammad Kanan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接