QLineEdit限制數據類型——只能輸入浮點型數


前言

最近做了一個小的上位機,要通過串口來下發幾個時間參數,為了防止誤輸入,產生不必要的麻煩,我把輸入范圍限制在0-680的浮點型數據,支持小數點后2位。學習了一下QLineEdit類是如何限制輸入類型的。本來是想寫一個函數,在下發參數時,傳QLineEdit的字符串參數進去,然后判斷是否合法,如果不合法,則不下發參數,請用戶修改后再確認。這么做也實現了,但是想Qt這么強大,應該會考慮到這一點的,所以找了個更簡單,在輸入的時候就限制數據的類型,不合法的根本輸入不進去。

關於QLineEdit類

QlineEdit是一個單行文本輸入框,支持撤銷、重做、復制、粘貼、拖放等操作,echomode模式支持,即只寫模式,可以輸入密碼等不可見的文本,官方介紹:QLineEdit Class

可以通過setValidator函數來限制數據類型,

setValidator函數的參數是QValidator,主要有3種:

  • QIntValidator //限制只能輸入整數,限制范圍
  • QDoubleValidator //限制只能輸入浮點數,包括范圍,小數點位數
  • QRegExpValidator //限制規則按指定的正則表達式

Amazing!QDoubleValidator不就是我想要的嗎?但是經過實際測試發現,其中QDoubleValidator可以限制浮點型數據和輸入的小數位數,但是並不能限制輸入范圍,也就是setRange,setBottom,setTop這些函數的設置並沒有生效,這難道是Qt的一個Bug?我的Qt版本是5.8.0,Qt Creator版本是4.2.1,而QRegExpValidator的使用就很強大了,需要了解正則表達式的相關知識。下面來詳細介紹一下這三種類的使用。

QIntValidator Class

  • 功能

    限制QLineEdit只能輸入int類型數據,即整型數據,包含正負整數和0

  • 相關函數

    //限制數據范圍
    QIntValidator(int minimum, int maximum, QObject *parent = Q_NULLPTR)
    //獲取最小值
    int bottom() 
    //設置最小值
    void setBottom(int)
    //設置數據范圍
    void setRange(int bottom, int top)
    //設置最大值
    void setTop(int)
    //獲取最大值
    int top() const
    
  • 示例

    //整型限制范圍100-999
    lineEdit->setValidator(new QIntValidator(100, 999, this));       
    
    //或者
    QIntValidator* aIntValidator = new QIntValidator;
    aIntValidator->setRange(100, 999);
    ui->le_L1->setValidator(aIntValidator);
    

QDoubleValidator Class

  • 功能

    限制QLineEdit只能輸入浮點型數據,可以指定輸入范圍及小數點位數

  • 相關函數

    //限制數據范圍
    QDoubleValidator(double bottom, double top, int decimals, QObject *parent = Q_NULLPTR)
    //設置小數點位數
    void setDecimals(int)
    //獲取設置的小數點位數
    int decimals() 
    //設置數字表示方式,標准計數法還是科學計數法
    void setNotation(Notation)
    //獲取設置的計數方式
    Notation notation() 
    //設置最小值
    void setBottom(double)
    //獲取設置的最小值
    double bottom() 
    //設置最大值
    void setTop(double)
    //獲取設置的最大值
    double top() 
    //設置數據范圍,默認無小數位
    void setRange(double minimum, double maximum, int decimals = 0)
    
    
  • 示例

//限制范圍0-680,小數點2位
lineEdit->setValidator(**new** QDoubleValidator(0,680,2,**this**));

限制范圍無效,這可能是Qt的一個Bug。

QRegExpValidator Class

  • 功能

    按照自定義的正則表達式規則,限制輸入的范圍。

  • 相關函數

//設置按正則表達式限制
QRegExpValidator(const QRegExp &rx, QObject *parent = Q_NULLPTR)
//獲取設置的正則表達式
QRegExp &regExp() 
//設置正則表達式
void setRegExp(const QRegExp &rx)
  • 示例
//限制-180,180,並限定小數點后4位
QRegExp rx("^-?(180|1?[0-7]?\\d(\\.\\d{1,4})?)$");  
QRegExpValidator *pReg = new QRegExpValidator(rx, this);  
lineEdit->setValidator(pReg);  

關於正則表達式

正則表達式,又稱規則表達式(英語:Regular Expression,在代碼中常簡寫為regex、regexp或RE),計算機科學的一個概念。正則表達式通常被用來檢索、替換那些符合某個模式(規則)的文本。許多程序設計語言都支持利用正則表達式進行字符串操作。例如,在Perl中就內建了一個功能強大的正則表達式引擎。正則表達式這個概念最初是由Unix中的工具軟件(例如sed和grep)普及開的。正則表達式通常縮寫成“regex”,單數有regexp、regex,復數有regexps、regexes、regexen。

關於正則表達式的詳細介紹:正則表達式30分鍾入門教程

//正則表達式說明:
/*

^(-?[0]|-?[1-9][0-9]{0,5})(?:\.\d{1,4})?$|(^\t?$)
(^-?180$)|(^-?1[0-7]\d$)|(^-?[1-9]\d$)|(^-?[1-9]$)|^0$
^-?(180|1?[0-7]?\d(\.\d+)?)$
^-?(180|1?[0-7]?\d(\.\d{1,4})?)$
^-?(90|[1-8]?\d(\.\d{1,4})?)$

 式子中開頭的^和結尾的$限定字符串的開始和結尾;
 "-?" 表示一個或0個負號,這里面的問號表示其前面的字符重復0次或1次;
 管道符“|”表示平行分組,比如后三個,表示180或其它形式;
 [1-9] 表示限定數字范圍為1到9,其余類似,如果是有限幾個值,還可以用枚舉的方式,比如限定-255到255時,第一個數字2的限定,應該表達為[1,2],這表示這個位置只允許是1或者2;
 "\d"是一個轉義字符,表示匹配一位數字;
 “\.” 表示匹配小數點;
 "\d+",這里面的+表示其前面的\d重復一次或多次;
 "\d{1,4}",里面的{1,4}表示重復1到4次;

*/

關於QDoubleValidator的Bug解決

網上搜索一遍,確實是Qt的Bug,需要重寫,下面是一個網友實現的MyDoubleValidator類。

  • 定義MyDoubleValidator類
class MyDoubleValidator : public QDoubleValidator
{
    Q_OBJECT
public:
    MyDoubleValidator(QObject *parent);
    ~MyDoubleValidator();
    virtual QValidator::State validate(QString &input, int &pos) const;
};
  • 函數實現
#include "MyDoubleValidator.h"

MyDoubleValidator::MyDoubleValidator(QObject *parent)
	: QDoubleValidator(parent)
{
}

MyDoubleValidator::~MyDoubleValidator()
{
}

QValidator:: State MyDoubleValidator::validate(QString & input, int & pos) const
{
	if (input.isEmpty())
	{
		return QValidator::Intermediate;
	}
	bool OK = false;
	double val = input.toDouble(&OK);

	if (!OK)
	{
		return QValidator::Invalid;
	}
	
	int dotPos = input.indexOf(".");
	if (dotPos > 0)
	{
		if (input.right(input.length() - dotPos - 1).length() > decimals())
		{
			return QValidator::Invalid;
		}
	}
	if(val<bottom()|| val>top())
		return QValidator::Invalid;
	return QValidator::Acceptable;
}
  • 實際應用
{
	MyDoubleValidator * dv = new  MyDoubleValidator(0);
	dv->setNotation(QDoubleValidator::StandardNotation);
	dv->setRange(2.0, 3.0, 2);
	ui.lineEdit->setValidator(dv); 
}

自定義函數的實現方式

一開始,我並不知道可以通過setValidator函數來實現數據類型限制,我直接實現了一個檢測輸入的QString類型數據是否是Float數據,並沒有指定小數后的位數,返回值為1表示是Float類型數據,否則不是。

  • 函數實現
int Dialog::FloatCheck(QString float_str)
{
    QByteArray ba = float_str.toLatin1();//QString 轉換為 char*
    const char *str = ba.data();

    int dotNum = 0;
    int dotIdx = 0;
    int Idx = 0;
    while(*str)
    {
        Idx++;
        if(*str == '.')
        {
            dotIdx = Idx;   //dot
            dotNum++;   	//dot個數統計
            if(dotNum > 1)  //小數點個數超過1
                return 0;
            else if((dotNum == 0 && dotIdx) || (dotNum == 1 && dotIdx == 1))    //無小數點
            {
                return 1;
            }
        }
        if(*str != '.')
        {
            if(*str < '0' || *str > '9')
                return 0;
        }
        str++;
    }
    return 1;
}
  • 測試驗證
/*

輸入:
    char *str1 = "1.2345";
    char *str2 = "a.2345";
    char *str3 = "0.2345";
    char *str4 = "1a2345";
    char *str5 = "a2345";
    char *str6 = "1.2.2345";
    char *str7 = "3.234.";
    char *str8 = "3.234.a";

輸出:

str1 : 1.2345 - 1
str2 : a.2345 - 0
str3 : 0.2345 - 1
str4 : 1a2345 - 0
str5 : a2345 - 0
str6 : 1.2.2345 - 0
str7 : 3.234. - 0
str8 : 3.234.a - 0

*/

歷史精選


歡迎關注我的個人博客www.wangchaochao.top

或微信掃碼關注我的公眾號


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM