2016-02-03 12 views
1

Позвольте мне использовать пример, чтобы объяснить проблему.DoubleValidator не проверяет диапазоны правильно

Если мы имеем TextField как это,

TextField { 
    text: "0.0" 
    validator: DoubleValidator { bottom: -359.9; 
     top: 359.9; 
     decimals: 1; 
     notation: DoubleValidator.StandardNotation } 

    onEditingFinished: { 
     console.log("I'm here!"); 
    }      
} 

Мы можем вводить цифры, такие как 444.9, 399.9 или -555.5. Как вы можете видеть, значения не находятся между -359.9 и 359.9.

В documentation можно найти следующую информацию:

Input принимается, но недопустимый, если он содержит двойной, которое вне диапазона или находится в неправильном формате; например со слишком большим числом цифр после десятичной точки или пустым.

Я думал, что DoubleValidator не принял такие вещи, но, к сожалению, это так.

Поэтому я предполагаю, что решение будет состоять в том, чтобы проверить окончательный ввод, но опять-таки у нас есть проблема: editingFinished испускается только в том случае, если валидатор возвращает приемлемое состояние, и это не всегда так.

Возможно, я не очень хорошо подхожу, я не понимаю, как использовать DoubleValidator или, может быть, мне нужен код на C++.

Кстати, я работаю с Qt 5.4.

+1

Двойной валидатор предотвращает принятие недопустимых значений при нажатии клавиши ввода. Разве это не то, что вы хотите? –

+0

@xsquared На самом деле, если я печатаю 500, «TextField» показывает это значение, и если я нажимаю клавишу ввода или меняю на другой «TextField» в окне, данные не очищаются. У вас есть небольшой пример, чтобы проверить, что вы сказали? – Tarod

+0

Я снова проверил документацию и действительно нашел проблему. Пожалуйста, прочтите мой ответ ниже, я надеюсь, что это поможет вам. –

ответ

0

Проблема заключается в том, что QML TextField принимает промежуточный вход:

валидаторов: Validator

Позволяет установить валидатор на TextField. Когда установлен валидатор, TextField будет только принять ввод, который оставляет свойство текста в промежуточном состоянии. Принимаемый сигнал будет отправлен только в том случае, если текст находится в приемлемом состоянии при нажатии клавиши ввода.

validate()-function of QDoubleValidator описывает, когда он возвращается QValidator::Intermediate:

Государственный QValidator :: Validate (QString & вход, внутр & Pos) константный

Эта виртуальная функция возвращает Invalid, если введено недопустимое в соответствии с правилами этого валидатора, Промежуточный, если возможно, что немного больше редактирования сделает вход приемлемым (например, пользователь вводит «4» в к виджету, который принимает целые числа от 10 до 99) и допустимо, если вход действителен.

Так что означает, валидатор возвращает QValidator::Intermediate, пока вводится двойное значение и потому, что TextField хорошо с «промежуточным», вы можете напечатать что угодно, пока это число.

Что вы можете сделать, это подкласс QDoubleValidator и переопределить validate(), так что он не возвращает Intermediate, когда значения выходят за границы:

class TextFieldDoubleValidator : public QDoubleValidator { 
public: 
    TextFieldDoubleValidator (QObject * parent = 0) : QDoubleValidator(parent) {} 
    TextFieldDoubleValidator (double bottom, double top, int decimals, QObject * parent) : 
    QDoubleValidator(bottom, top, decimals, parent) {} 

    QValidator::State validate(QString & s, int & pos) const { 
     if (s.isEmpty() || s.startsWith("-")) { 
      // allow empty field or minus sign 
      return QValidator::Intermediate; 
     } 
     // check length of decimal places 
     QChar point = locale().decimalPoint(); 
     if(s.indexOf(point) != -1) { 
      int lengthDecimals = s.length() - s.indexOf(point) - 1; 
      if (lengthDecimals > decimals()) { 
       return QValidator::Invalid; 
      } 
     } 
     // check range of value 
     bool isNumber; 
     double value = locale().toDouble(s, &isNumber); 
     if (isNumber && bottom() <= value && value <= top()) { 
      return QValidator::Acceptable; 
     } 
     return QValidator::Invalid; 
    } 

}; 
+1

Очень хороший ответ! Однако я столкнулся с несколькими проблемами, которые я хотел бы рассказать. 'MyValidator' должен быть' TextFieldDoubleValidator' и 'return QValidator :: Invalid;' находится вне функции 'validate'. Мне нужно интегрировать этот новый компонент в мое приложение QML, но у меня были некоторые ошибки компиляции. Чтобы решить их, мне пришлось добавить новый конструктор 'TextFieldDoubleValidator (QObject * parent = 0): QDoubleValidator (parent) {}'. Пожалуйста, дайте мне свое мнение обо всем этом. – Tarod

+0

Благодарю вас, я включил ваши исправления, все они действительны. –

+0

Отлично! Благодаря вам :) – Tarod

0

Ответ предоставляется @xsquared был совершенен. Я думаю, что это хорошая идея поделиться с кем-то любопытным, как интегрировать решение с QML.

TextFieldDoubleValidator - класс, который предложил @xsquared.

Итак, первое, что нужно зарегистрировать новый тип в нашем основном.

main.cpp

#include <QGuiApplication> 
#include <QQmlApplicationEngine> 
#include <QtQml> 
#include "textfielddoublevalidator.h" 

int main(int argc, char *argv[]) 
{ 
    QGuiApplication app(argc, argv); 
    qmlRegisterType<TextFieldDoubleValidator>("TextFieldDoubleValidator", 1,0, 
               "TextFieldDoubleValidator"); 

    QQmlApplicationEngine engine; 
    engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); 

    return app.exec(); 
} 

После этого, мы можем использовать новый тип в нашем QML применения:

main.qml

import QtQuick 2.5 
import QtQuick.Window 2.2 
import QtQuick.Controls 1.4 
import TextFieldDoubleValidator 1.0 

Window { 
    visible: true 

    // DoubleValidator doesn't clear the TextField when 
    // text > 359.9 or < -359.9 
    TextField { 
     text: "0.0" 
     validator: DoubleValidator { 
      bottom: -359.9; 
      top: 359.9; 
      decimals: 1; 
      notation: DoubleValidator.StandardNotation 
     } 
    } 

    // Solution: use your own DoubleValidator. 
    // This works OK and text is cleared out when 
    // text > 359.9 or < -359.9 
    TextField { 
     y: 50 
     text: "0.0" 
     validator: TextFieldDoubleValidator { 
      bottom: -359.9; 
      top: 359.9; 
      decimals: 1; 
      notation: DoubleValidator.StandardNotation 
     } 
    } 
} 
1

Вот чистый qml версия:

TextFieldInput{ 
validator: DoubleValidator 
{ 
    bottom: minimumValue 
    top: maximumValue 
} 

property real maximumValue: constants._MAXIMUM_INTEGER 
property real minimumValue: constants._MINIMUM_INTEGER 
property string previousText: "" 

onTextChanged: 
{ 
    var numericValue = getValue() 
    if (numericValue > maximumValue || numericValue < minimumValue) 
    { 
     text = previousText 
    } 
    previousText = text 
} 

function setValue(_value) 
{ 
    text = String(_value) 
} 

function getValue() 
{ 
    return Number(text) 
}} 

 Смежные вопросы

  • Нет связанных вопросов^_^