C++ 仅允许QLineEdit中的条目在QDoubleValidator的范围内
我有一组C++ 仅允许QLineEdit中的条目在QDoubleValidator的范围内,c++,qt,validation,qlineedit,C++,Qt,Validation,Qlineedit,我有一组QLineEdits,它们应该接受特定范围内的双值(例如-15到15) 在设置每一个时,我都有以下内容: lineEdit->setValidator(new QDoubleValidator(minVal, maxVal, 5, lineEdit)); 理想情况下,行编辑可以只输入范围内的值。当我尝试这个方法时,我注意到只有数字可以按需要输入,但它们仍然可能超出范围 如何动态强制输入适应范围(例如,如果范围为-15到15,用户键入1,然后尝试键入9,它不工作/显示9…但键入1,
QLineEdits
,它们应该接受特定范围内的双值(例如-15到15)
在设置每一个时,我都有以下内容:
lineEdit->setValidator(new QDoubleValidator(minVal, maxVal, 5, lineEdit));
理想情况下,行编辑可以只输入范围内的值。当我尝试这个方法时,我注意到只有数字可以按需要输入,但它们仍然可能超出范围
如何动态强制输入适应范围(例如,如果范围为-15到15,用户键入1,然后尝试键入9,它不工作/显示9…但键入1,然后键入2可以工作/显示2。)
我需要在某个地方连接并调用
validate()
函数吗?这是因为QDoubleValidator
返回QValidator::Intermediate
如果值超出边界并且QLineEdit
接受QValidator::Intermediate
值
要实现您想要的行为,您可以创建自己的QDoubleValidator
子类,如下所示:
class MyValidator : public QDoubleValidator
{
public:
MyValidator(double bottom, double top, int decimals, QObject * parent) :
QDoubleValidator(bottom, top, decimals, parent)
{
}
QValidator::State validate(QString &s, int &i) const
{
if (s.isEmpty()) {
return QValidator::Intermediate;
}
bool ok;
double d = s.toDouble(&ok);
if (ok && d > 0 && d < 15) {
return QValidator::Acceptable;
} else {
return QValidator::Invalid;
}
}
};
类MyValidator:公共QDoubleValidator
{
公众:
MyValidator(双底、双顶、整数小数、QObject*父项):
QDoubleValidator(底部、顶部、小数、父级)
{
}
QValidator::状态验证(QString&s、int&i)常量
{
如果(s.isEmpty()){
返回QValidator::Intermediate;
}
布尔ok;
双d=s.toDouble(&ok);
如果(ok&&d>0&&d<15){
返回QValidator::可接受;
}否则{
返回QValidator::无效;
}
}
};
更新:这将解决负号问题,还将接受区域设置双格式:
class MyValidator : public QDoubleValidator
{
public:
MyValidator(double bottom, double top, int decimals, QObject * parent) :
QDoubleValidator(bottom, top, decimals, parent)
{
}
QValidator::State validate(QString &s, int &i) const
{
if (s.isEmpty() || s == "-") {
return QValidator::Intermediate;
}
QChar decimalPoint = locale().decimalPoint();
if(s.indexOf(decimalPoint) != -1) {
int charsAfterPoint = s.length() - s.indexOf(decimalPoint) - 1;
if (charsAfterPoint > decimals()) {
return QValidator::Invalid;
}
}
bool ok;
double d = locale().toDouble(s, &ok);
if (ok && d >= bottom() && d <= top()) {
return QValidator::Acceptable;
} else {
return QValidator::Invalid;
}
}
};
类MyValidator:公共QDoubleValidator
{
公众:
MyValidator(双底、双顶、整数小数、QObject*父项):
QDoubleValidator(底部、顶部、小数、父级)
{
}
QValidator::状态验证(QString&s、int&i)常量
{
如果(s.isEmpty()| | s==“-”){
返回QValidator::Intermediate;
}
QChar decimalPoint=locale().decimalPoint();
如果(s.indexOf(小数点)!=-1){
int charsAfterPoint=s.length()-s.indexOf(decimalPoint)-1;
if(charsAfterPoint>decimals()){
返回QValidator::无效;
}
}
布尔ok;
双d=locale().toDouble(s,&ok);
如果(ok&&d>=bottom()&&d我尝试了上面的优秀类,但它仍然需要进行一些编辑。小数点搜索正在缩小“top”指定的范围,因为它在没有小数点时返回“-1”。我添加了一个条件语句来解决这个问题
此外,如果用户试图删除小数点,并且结果值大于范围,则仍需要对其进行调整。现在它只是禁止该行为,而不是将其更改为最大值,这对我来说更直观
class MyValidator : public QDoubleValidator
{
public:
MyValidator(double bottom, double top, int decimals, QObject * parent) :
QDoubleValidator(bottom, top, decimals, parent)
{
}
QValidator::State validate(QString &s, int &i) const
{
if (s.isEmpty() || s == "-") {
return QValidator::Intermediate;
}
QLocale locale;
QChar decimalPoint = locale.decimalPoint();
int charsAfterPoint = s.length() - s.indexOf(decimalPoint) -1;
if (charsAfterPoint > decimals() && s.indexOf(decimalPoint) != -1) {
return QValidator::Invalid;
}
bool ok;
double d = locale.toDouble(s, &ok);
if (ok && d >= bottom() && d <= top()) {
return QValidator::Acceptable;
} else {
return QValidator::Invalid;
}
}
};
类MyValidator:公共QDoubleValidator
{
公众:
MyValidator(双底、双顶、整数小数、QObject*父项):
QDoubleValidator(底部、顶部、小数、父级)
{
}
QValidator::状态验证(QString&s、int&i)常量
{
如果(s.isEmpty()| | s==“-”){
返回QValidator::Intermediate;
}
QLocale语言环境;
QChar decimalPoint=locale.decimalPoint();
int charsAfterPoint=s.length()-s.indexOf(decimalPoint)-1;
if(charsAfterPoint>decimals()&&s.indexOf(decimalPoint)!=-1){
返回QValidator::无效;
}
布尔ok;
双d=locale.toDouble(s,&ok);
如果(ok&&d>=bottom()&&d在检查QLineEdit
输入的可接受范围时,我花了几乎一天的时间试图让QDoubleValidator
与合理的用户反馈一起工作。我尝试使用Qt时规定了validator::fixup()
结果是浪费时间。本帖中的早期答案更有用,但仍有不足之处。最后,我选择了一种不同且更简单的方法
为QLineEdit
配备不执行范围检查的QDoubleValidator
在QLineEdit
编辑的处理程序中,完成
信号范围检查,必要时重置QLineEdit
文本
这种方法不允许键入非法字符,负责本地化并更正超出所需范围的值
对我来说效果很好。也可以在不使用子类的情况下完成这项工作
lineEdit = new QLineEdit();
connect(lineEdit,SIGNAL(textChanged(QString)), this, SLOT(textChangedSlot(QString)));
QDoubleValidator *dblVal = new QDoubleValidator(minVal, maxVal, 1000, lineEdit);
dblVal->setNotation(QDoubleValidator::StandardNotation);
dblVal->setLocale(QLocale::C);
lineEdit->setValidator(dblVal);
区域设置可能很重要,因为它定义了哪些字符被解释为十进制分隔符。输入字符串的格式定义了应该使用哪些区域设置
在textChangedSlot中,我们可以通过以下方式验证输入:
QString str = lineEdit->text();
int i = 0;
QDoubleValidator *val = (QDoubleValidator *) lineEdit->validator();
QValidator::State st = val->validate(str, i);
if (st == QValidator::Acceptable) {
// Validation OK
} else {
// Validation NOK
}
在这种情况下,QValidator::Intermediate状态也被解释为失败的情况
如果我们将textChanged-signal连接到textChangedSlot,则每次输入字段更改后都会进行验证。我们还可以连接editingFinished()或returnPressed()-向验证槽发送信号。在这种情况下,只有当用户停止编辑字符串时才进行验证。VVV的答案对于原始问题nicole非常有效。这是从负到正的范围
但是,作为QDoubleValidator的通用解决方案,当范围从正到正时,它有一个副作用:
示例:范围:[87.5…1000.0],输入:“15”(作为中间值达到150)
当QLineEdit低于下限(或开始为空)时,输入将被拒绝。因此,我扩展了VVV的解决方案作为一般解决方案:
/*
* Empty string and the negative sign are intermediate
*/
if( input.isEmpty() || input == "-" )
{
return QValidator::Intermediate;
}
/*
* Check numbers of decimals after the decimal point
* and the number of decimal points
*/
QChar decimalPoint = locale().decimalPoint();
if( input.count( decimalPoint, Qt::CaseInsensitive ) > 1 )
{
return QValidator::Invalid;
}
else if( input.indexOf( decimalPoint ) != -1)
{
const int charsAfterPoint = input.length() - input.indexOf( decimalPoint) - 1;
if( charsAfterPoint > decimals() )
{
return QValidator::Invalid;
}
}
/*
* Check for valid double conversion and range
*/
bool ok;
const double d = locale().toDouble( input, &ok );
if( ok && d <= top() )
{
if( d >= bottom() )
{
return QValidator::Acceptable;
}
else
{
return QValidator::Intermediate;
}
}
else
{
return QValidator::Invalid;
}
/*
*空字符串和负号是中间的
*/
if(input.isEmpty()||
#include <QDoubleValidator>
class TruncationValidator : public QDoubleValidator
{
Q_OBJECT
public:
explicit TruncationValidator(QObject *parent = 0) : QDoubleValidator(parent) {
connect(this->parent(), SIGNAL(editingFinished()), this, SLOT(truncate()));
}
TruncationValidator(double bottom, double top, int decimals, QObject * parent) : QDoubleValidator(bottom, top, decimals, parent) {
connect(this->parent(), SIGNAL(editingFinished()), this, SLOT(truncate()));
}
QValidator::State validate(QString &s, int &i) const {
QValidator::State state = QDoubleValidator::validate(s,i);
if (s.isEmpty()) {
return state;
}
bool ok;
double d = s.toDouble(&ok);
if (ok) {
// QDoubleValidator returns QValidator::Intermediate if out of bounds
return QValidator::Acceptable;
}
return state;
}
private slots:
void truncate() {
QLineEdit* le = dynamic_cast<QLineEdit*>(parent());
if (le) {
QString s = le->text();
bool ok;
double d = s.toDouble(&ok);
if (ok) {
if (d > this->top() || d < this->bottom()) {
d = std::min<double>(d, this->top());
d = std::max<double>(d, this->bottom());
le->setText(QString::number(d));
}
}
}
}
private:
};