前言

最近做了一個小的上位機,要通過串口來下發幾個時間參數,為了防止誤輸入,產生不必要的麻煩,我把輸入範圍限制在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

  • 相關函數

c++ //限制數據範圍 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

  • 示例: ```c++ //整型限制範圍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只能輸入浮點型數據,可以指定輸入範圍及小數點位數

  • 相關函數

    ```c++ //限制數據範圍 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})?$|(^ ?$)
(^-?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

*/

歷史精選

  • Qt實現軟體自動更新的一種簡單方法
  • Qt小項目之串口助手控制LED
  • 真正的RISC-V開發板——VEGA織女星開發板開箱評測
  • 手把手教你製作Jlink-OB調試器(含原理圖、PCB、外殼、固件)

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

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


推薦閱讀:
相关文章