2012-04-12 1 views
2

Я пытаюсь расширить QSpinBox, чтобы иметь возможность вводить «NaN» или «nan» в качестве допустимого значения. Согласно документации, я должен использовать textFromValue, valueFromText и проверять функции, чтобы выполнить это, но я не могу заставить его работать, поскольку он все еще не позволяет мне вводить текст, кроме цифр. Вот что я имею в моих .h и .cpp файлов:QSpinBox вводит NaN в качестве действительного значения

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 

Есть ли что-то им не хватает? или делать не так? Если theres и более простой способ сделать это, также было бы здорово знать ...

+0

Некоторые предложения относительно вашего кода, независимо от вопроса: (1) Не используйте спецификацию броска, если вы должны, так как базовый класс делает ([Sutter/Alexandrescu] (Http: // www.amazon.com/Coding-Standards-Rules-Guidelines-Practices/dp/0321113586), пункт 75). (2) Сделайте ваш ctor 'явным' (ibid, пункт 40). (3) Не пишите 'using namespace' в заголовке (там же, пункт 59). (4) Используйте 'static const int NAN_VALUE = 32767;' вместо '# define' (там же, пункт 16). (5) Не '#include ' (замедляет компиляцию). (6) Используйте 'QLatin1String (« nan »)' вместо 'QString :: fromStdString (« nan »)' (быстрее). –

ответ

4

Подпись QAbstractSpinBox::validate() является:

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

Так подпись вашего validate() метода отличается двумя способами: его не const, и у вас есть int pos вместо int& pos. Таким образом, он не отменяет QAbstractSpinBox::validate и никогда не вызывается QAbstractSpinBox.

+0

Спасибо большое! это была проблема. – MBU

+0

Если бы я хотел сделать то же самое для QDoubleSpinBox, будет ли этот код работать? или мне придется изменить функции для учета десятичной точки в тексте? – MBU

1

Возможно, QSpinBox устанавливает строкуEdit с QIntValidator как QValidator. По крайней мере, документы QAbstractSpinBox :: setLineEdit показывают, что валидатор линииEdit имеет приоритет над функцией QAbstractSpinBox :: validate.

2

Если вы можете расширить нижнюю границу своего диапазона от -1 и использовать обычный QSpinBox или QDoubleSpinBox и вызвать spinbox->specialValueText("nan"), который будет показывать строку nan когда value() == minimum(). Пользователь не сможет ввести строку «нан» вручную, но вы всегда можете сопровождать проигрыватель с помощью кнопки, которая выполняет spinbox->setValue(spinbox->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"