Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QLineEdit autofill



  • Hello,

    i would like to know how to automatically correct the numerical value upon the input.
    let's say, i type 10K in the QLineEdit field, but on the back i want this number autocratically translated into 10000.

    aswel if i type 1N (Nano), that it would adjust the value to 0.000001.

    would what the procedure?

    regards



  • Something like:

    #include <QLineEdit>
    #include <QValidator>
    #include <QRegularExpression>
    #include <QApplication>
    
    class FixingValidator : public QDoubleValidator{
        Q_DISABLE_COPY(FixingValidator)
    public:
        using QDoubleValidator::QDoubleValidator;
        State validate(QString & input, int & pos) const override{
            const QRegularExpressionMatch res = vaidRegExp.match(input);
            if(!res.hasMatch())
                return Invalid;
            QString nemericPart = res.captured(1);
            if(res.lastCapturedIndex()==1)
                return QDoubleValidator::validate(nemericPart,pos);
            else
                return QDoubleValidator::validate(nemericPart,pos) == Invalid ? Invalid : Intermediate;
        }
        void fixup(QString &input) const override{
            const QRegularExpressionMatch res = vaidRegExp.match(input);
            if(!res.hasMatch())
                return;
            if(res.capturedRef(2).isEmpty())
                return;
            double baseNumber = locale().toDouble(res.capturedRef(1));
            switch(res.capturedRef(2).at(0).unicode()){
            case 'k':
            case 'K':
                input=locale().toString(baseNumber*1000.0);
                break;
            case 'n':
            case 'N':
                input=locale().toString(baseNumber/1000000.0);
                break;
            }
        }
    private:
        const QRegularExpression vaidRegExp=QRegularExpression(QStringLiteral(R"**(^(.+?)([kKnN]?)$)**"));
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QLineEdit laxEdit;
        FixingValidator* valid= new FixingValidator(&laxEdit);
        QObject::connect(&laxEdit,&QLineEdit::textChanged,[&laxEdit,valid](const QString& txt){
            QString oldText=txt;
            valid->fixup(oldText);
            laxEdit.setText(oldText);
        });
        laxEdit.setValidator(valid);
        laxEdit.show();
        return a.exec();
    }
    
    


  • Something like:

    #include <QLineEdit>
    #include <QValidator>
    #include <QRegularExpression>
    #include <QApplication>
    
    class FixingValidator : public QDoubleValidator{
        Q_DISABLE_COPY(FixingValidator)
    public:
        using QDoubleValidator::QDoubleValidator;
        State validate(QString & input, int & pos) const override{
            const QRegularExpressionMatch res = vaidRegExp.match(input);
            if(!res.hasMatch())
                return Invalid;
            QString nemericPart = res.captured(1);
            if(res.lastCapturedIndex()==1)
                return QDoubleValidator::validate(nemericPart,pos);
            else
                return QDoubleValidator::validate(nemericPart,pos) == Invalid ? Invalid : Intermediate;
        }
        void fixup(QString &input) const override{
            const QRegularExpressionMatch res = vaidRegExp.match(input);
            if(!res.hasMatch())
                return;
            if(res.capturedRef(2).isEmpty())
                return;
            double baseNumber = locale().toDouble(res.capturedRef(1));
            switch(res.capturedRef(2).at(0).unicode()){
            case 'k':
            case 'K':
                input=locale().toString(baseNumber*1000.0);
                break;
            case 'n':
            case 'N':
                input=locale().toString(baseNumber/1000000.0);
                break;
            }
        }
    private:
        const QRegularExpression vaidRegExp=QRegularExpression(QStringLiteral(R"**(^(.+?)([kKnN]?)$)**"));
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QLineEdit laxEdit;
        FixingValidator* valid= new FixingValidator(&laxEdit);
        QObject::connect(&laxEdit,&QLineEdit::textChanged,[&laxEdit,valid](const QString& txt){
            QString oldText=txt;
            valid->fixup(oldText);
            laxEdit.setText(oldText);
        });
        laxEdit.setValidator(valid);
        laxEdit.show();
        return a.exec();
    }
    
    


  • @VRonin

    thank your very much.

    i copied it to my project, first the class and compiled, everything ok.
    but than ...

    FixingValidator* valid= new FixingValidator(&ui->lineEdit_1);
    

    results in:

    error: no matching function for call to 'FixingValidator::FixingValidator(QLineEdit**)'
         FixingValidator* valid= new FixingValidator(&ui->lineEdit_1);
    

    i'm using a standard "project" with the designer and i try to reference the object in the *.ui file.
    i have 4 QLineEdits on my "form" on witch i want to apply this effect.



  • @Natural_Bugger hi
    a shoot in the dark

    FixingValidator* valid= new FixingValidator(ui->lineEdit_1);

    instead of

    FixingValidator* valid= new FixingValidator(&ui->lineEdit_1);



  • @LeLev

    thank your very much, this error is eliminated.
    but the next line contains 4/5 errors.
    after correcting to your previous answer.

    QObject::connect(ui->lineEdit_1,&QLineEdit::textChanged,[ui->lineEdit_1,valid](const QString& txt){
    

    errors:

    error: capture of non-variable 'MainWindow::ui'
             QObject::connect(ui->lineEdit_1,&QLineEdit::textChanged,[ui->lineEdit_1,valid](const QString& txt){
    
    
                                                                             ^
    
    error: expected ',' before '->' token
             QObject::connect(ui->lineEdit_resistor,&QLineEdit::textChanged,[ui->lineEdit_resistor,valid](const QString& txt){
                                                                               ^
    
    error: expected identifier before '->' token
    
    error: expected ']' before ',' token
             QObject::connect(ui->lineEdit_1,&QLineEdit::textChanged,[ui->lineEdit_1,valid](const QString& txt){
                                                                                                  ^
    
    In lambda function:
    
     error: expected '{' before ',' token
    
    In constructor 'MainWindow::MainWindow(QWidget*)':
    
    error: expected ')' before ']' token
             QObject::connect(ui->lineEdit_1,&QLineEdit::textChanged,[ui->lineEdit_1,valid](const QString& txt){
                                                                                                        ^
    


  • if you remove "[" & "]", than ...

    2 errors remain.

    expected primary-expression before 'const'
             QObject::connect(ui->lineEdit_1,&QLineEdit::textChanged,ui->lineEdit_1,valid(const QString& txt){
                                                                                                        ^
    
    error: 'valid' cannot be used as a function
             QObject::connect(ui->lineEdit_1,&QLineEdit::textChanged,ui->lineEdit_1,valid(const QString& txt){
                                                                                                                          ^
    

    than i changed ...

    valid(const QString& txt) into valid->fixup(const QString& txt)

     QObject::connect(ui->lineEdit_1,&QLineEdit::textChanged,ui->lineEdit_1,valid->fixup(const QString& txt){
    

    than i tried:

    QObject::connect(ui->lineEdit_1,&QLineEdit::textChanged,ui->lineEdit_1,valid->fixup(ui->lineEdit_1->text()){
    

    but ...

    error: invalid initialization of non-const reference of type 'QString&' from an rvalue of type 'QString'
             QObject::connect(ui->lineEdit_1,&QLineEdit::textChanged,ui->lineEdit_1,valid->fixup(ui->lineEdit_1->text()){
                                                                                                                                          ^
    
    note:   initializing argument 1 of 'virtual void FixingValidator::fixup(QString&) const'
         void fixup(QString &input) const override{
              ^
    


  • just replace [ui->lineEdit_1,valid] with [=]



  • @VRonin

    Awesome!

    but i have 2 different types of fields, but 4 on total on witch i wanna apply this effect.

    FixingValidator* valid= new FixingValidator(ui->lineEdit_1);
    ...
    ..
    .
    FixingValidator* valid= new FixingValidator(ui->lineEdit_2);
    ...
    ..
    .
    

    i extended the class, ...

        void fixup(QString &input) const override{
                const QRegularExpressionMatch res = vaidRegExp.match(input);
                if(!res.hasMatch())
                    return;
                if(res.capturedRef(2).isEmpty())
                    return;
                double baseNumber = locale().toDouble(res.capturedRef(1));
                switch(res.capturedRef(2).at(0).unicode()){
                case 'k':
                case 'K':
                    input=locale().toString(baseNumber*1000.0);
                    break;
                case 'n':
                case 'N':
                    input=locale().toString(baseNumber*1000000.0);
                    break;
                }
            }
        
            void fixup2(QString &input) const override{
                const QRegularExpressionMatch res = vaidRegExp.match(input);
                if(!res.hasMatch())
                    return;
                if(res.capturedRef(2).isEmpty())
                    return;
                double baseNumber = locale().toDouble(res.capturedRef(1));
                switch(res.capturedRef(2).at(0).unicode()){
                case 'k':
                case 'K':
                    input=locale().toString(baseNumber/1000.0);
                    break;
                case 'n':
                case 'N':
                    input=locale().toString(baseNumber/1000000.0);
                    break;
                }
            }
        
    

    results in:

    error: 'void FixingValidator::fixup2(QString&) const' marked 'override', but does not override
         void fixup2(QString &input) const override{
              ^
    

    i see that "virtual void fixup(QString &) const;" is part of QValidator.h
    what's to do?


  • Lifetime Qt Champion

    @Natural_Bugger said in QLineEdit autofill:

    error: 'void FixingValidator::fixup2(QString&) const' marked 'override', but does not override

    Why fixup2?
    fixup2 != fixup



  • @jsulm

    because i have 2 different type of QLineEdits formfields, one takes numbers bigger than 0 and the other takes number smaller than 0.

    so i tried to extented the class and add an another method, called fixup2.


  • Lifetime Qt Champion

    @Natural_Bugger If you add a method which does not exist in the base class then you can't use override keyword as there is no such method in base class to override. So, remove override.



  • @jsulm

    it works, thank you very much.



  • i still have problem with numbers containing a number using the method:
    fixup2(QString &input).

    1,2e-07
    0,00012
    

    those that contain a comma.

    case 'n':
    case 'N':
                    input=locale().toString(baseNumber/1000000.0);
                    break;
    

    **"120n"**results in "0,00012" and doesn't work.
    **"10n"**results in "1e-05" and does work.

    no calculatiion takes place.

    if(ui->lineEdit_1.toFloat() == 0.0){
           QMessageBox::information(this, "empty","",QMessageBox::Ok);
    }
    

    this gets triggered.


Log in to reply