【问题标题】:QSpinBox enter NaN as a valid valueQSpinBox 输入 NaN 作为有效值
【发布时间】:2012-04-12 23:37:33
【问题描述】:

我正在尝试扩展 QSpinBox 以便能够输入“NaN”或“nan”作为有效值。根据文档,我应该使用 textFromValue、valueFromText 和 validate 函数来完成此操作,但我无法让它工作,因为它仍然不允许我输入除数字之外的任何文本。这是我的 .h 和 .cpp 文件中的内容:

CPP 文件:

#include "CustomIntSpinBox.h"

CustomIntSpinBox::CustomIntSpinBox(QWidget *parent) : QSpinBox(parent)
{
    this->setRange(-32767,32767);
}

QString CustomIntSpinBox::textFromValue(int value) const
{
    if (value == NAN_VALUE)
    {
        return QString::fromStdString("nan");
    }
    else
    {
        return QString::number(value);
    }
}

int CustomIntSpinBox::valueFromText(const QString &text) const
{
    if (text.toLower() == QString::fromStdString("nan"))
    {
        return NAN_VALUE;
    }
    else
    {
        return text.toInt();
    }
}

QValidator::State validate(QString &input, int pos)
{
    return QValidator::Acceptable;
}

H 文件:

#ifndef CUSTOMINTSPINBOX_H
#define CUSTOMINTSPINBOX_H

#include <QSpinBox>
#include <QWidget>
#include <QtGui>
#include <iostream>

using namespace std;

#define NAN_VALUE 32767

class CustomIntSpinBox : public QSpinBox
{
    Q_OBJECT

public:
    CustomIntSpinBox(QWidget *parent = 0);
    virtual ~CustomIntSpinBox() throw() {}

    int valueFromText(const QString &text) const;
    QString textFromValue(int value) const;
    QValidator::State validate(QString &input, int pos);
};

#endif // CUSTOMINTSPINBOX_H

我有什么遗漏吗?还是做错了?如果有更简单的方法来做到这一点,那就太好了......

【问题讨论】:

  • 关于您的代码的一些建议,与问题无关:(1) 不要使用 throw 规范,除非您必须这样做,因为基类确实如此(Sutter/Alexandrescu,第 75 条)。 (2) 让您的 ctor explicit(同上,第 40 条)。 (3) 不要在标题中写using namespace(同上,第 59 条)。 (4) 使用static const int NAN_VALUE = 32767; 代替#define(同上,第16 项)。 (5) 不要#include &lt;QtGui&gt;(减慢编译速度)。 (6) 使用QLatin1String("nan") 代替QString::fromStdString("nan")(更快)。

标签: c++ qt qspinbox


【解决方案1】:

QAbstractSpinBox::validate()的签名是:

QValidator::State QAbstractSpinBox::validate ( QString & input, int & pos ) const

所以您的validate() 方法的签名在两个方面有所不同:它不是const,并且您有int pos 而不是int&amp; pos。因此它不会覆盖QAbstractSpinBox::validate,也不会被QAbstractSpinBox 调用。

【讨论】:

  • 非常感谢!这就是问题所在。
  • 如果我想为 QDoubleSpinBox 做同样的事情,这段代码还能工作吗?还是我必须更改函数以考虑文本中的小数点?
【解决方案2】:

如果您可以将范围的下限扩展 -1 并使用普通的 QSpinBoxQDoubleSpinBox 并调用 spinbox-&gt;specialValueText("nan"),这将在 value() == minimum() 时显示字符串 nan。用户将无法手动输入字符串“nan”,但您始终可以在 spinbox 旁边添加一个执行 spinbox-&gt;setValue(spinbox-&gt;minimum()) 的按钮。这是一个可编译的示例:

// main.cpp
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QDialog>
#include <QApplication>
#include <QVBoxLayout>

#include <limits>

class Tester : public QDialog {
    Q_OBJECT
public:
    static const int NanValue = -32767-1;
    explicit Tester(QWidget * parent=0)
        : QDialog(parent),
          m_spinBox(new QSpinBox(this)),
          m_doubleSpinBox(new QDoubleSpinBox(this))
    {
        QVBoxLayout * vlay = new QVBoxLayout(this);
        vlay->addWidget(m_spinBox);
        vlay->addWidget(m_doubleSpinBox);

        m_spinBox->setRange(NanValue,32767);
        m_doubleSpinBox->setRange(NanValue,32767);

        m_spinBox->setValue(NanValue);
        m_doubleSpinBox->setValue(NanValue);

        updateSpecialValueText();
    }

protected:
    void changeEvent(QEvent *e) {
        QDialog::changeEvent(e);
        if (e->type() == QEvent::LocaleChange)
            updateSpecialValueText();
    }


private:
    void updateSpecialValueText() {
        static const double NaN = std::numeric_limits<double>::quiet_NaN();
        m_spinBox->setSpecialValueText(locale().toString(NaN));
        m_doubleSpinBox->setSpecialValueText(locale().toString(NaN));
    }

private:
    QSpinBox * m_spinBox;
    QDoubleSpinBox * m_doubleSpinBox;
};

int main(int argc, char * argv[]) {
    QApplication app(argc, argv);

    Tester t;
    return t.exec();
}

#include "main.moc"

【讨论】:

    【解决方案3】:

    也许 QSpinBox 设置了一个 lineEdit,它有一个 QIntValidator 作为 QValidator。至少 QAbstractSpinBox::setLineEdit 的文档表明 lineEdit 的验证器优先于 QAbstractSpinBox::validate 函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-31
      • 1970-01-01
      • 2023-04-03
      • 2016-11-19
      • 2019-07-14
      • 1970-01-01
      • 1970-01-01
      • 2017-12-07
      相关资源
      最近更新 更多