IP editing box (official, online, custom) - QtWidget

Preface

Recently, the IP editing box has been used on the gadget interface. Currently, the editing box QLineEdit is directly placed. Because it is for personal use, there is no need to write many restrictions. But if you have extra time, try using the official one (that is, set up directly on the basis of QLineEdit), the online one (spliced ​​by QLineEdit), and the customized one (online one plus self-improvement).

Effect

accomplish

Official (single QLineEdit)

The official one is to set the regular expression and mask directly on a single QLineEdit. The code is as follows, but the effect is not very good:

  • The cursor is thick and black, and it belongs to the mode of selecting and modifying a single character;
  • The content is not scattered throughout the box, and the alignment does not look good whether it is changed to the center or to the left;
  • Also, if you set the placeholder to a space, you won't be able to tell which number the current number is. I often select the second number, and then enter 192, and it directly becomes 19.2.
    QRegExp rx("((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)");
    QRegExpValidator *pReg = new QRegExpValidator(rx, this);
    ui->lineEdit->setValidator(pReg);
    ui->lineEdit->setInputMask("000.000.000.000; ");

Description of each symbol in regular expressions: 

  • \d: matches a number, equivalent to [0-9]
  • \.: matches a decimal point
  • ?: Indicates repeating the previous content 0 or 1 times
  • 2[0-4]\\d: Covers values ​​between 200~249
  • 25[0-5]: Covers values ​​between 250 and 255
  • [01]?\\d\\d?: Covers values ​​between 0~199

Regular expression online testing tool: Regular expression online testing | Rookie tool

Online (multiple QLineEdit splicing)

I found one on github, the address is: https://github.com/KingBright965/QtIPEdit/blob/master/IPEdit.cpp

  • Overall and content control : It is composed of multiple QLineEdits plus QLabel. Each QLineEdit is set with a regular expression. At the same time, in order to control the maximum length of each part to 3, the content editing of the edit box is monitored and controlled. The current length is 3, go to the next edit box;
void IPEdit::initForEdit(QLineEdit* edit)
{
    edit->setFrame(false);
    edit->setAlignment(Qt::AlignCenter);
    edit->installEventFilter(this);
    
    QRegExpValidator* validator = new QRegExpValidator(QRegExp("^(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$"), this);
    edit->setValidator(validator);
    
    connect(edit, SIGNAL(textChanged(const QString&)), this, SLOT(editTextChanged(const QString&)));
}
void IPEdit::editTextChanged(const QString& text)
{
    QLineEdit* curEdit = qobject_cast<QLineEdit*>(sender());
    if (text.size() == 3)
    {
        QLineEdit* next = nextEdit(curEdit);
        if (next)
        {
            next->setFocus();
            next->selectAll();
        }
    }
}
  •  Event response : and added event filtering, monitoring key points (Qt::Key_Period) and paste events (QKeySequence::Paste);
bool IPEdit::eventFilter(QObject* object, QEvent* event)
{
    if (isEdit(object))
    {
        if (event->type() == QEvent::KeyPress)
        {
            QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
            if (keyEvent->key() == Qt::Key_Period)
            {
                QLineEdit* next = nextEdit(qobject_cast<QLineEdit*>(object));
                if (next)
                {
                    next->setFocus();
                    next->selectAll();
                }
            }
            else if (keyEvent->matches(QKeySequence::Paste))
            {
                QString clip = QApplication::clipboard()->text(QClipboard::Clipboard);
                if (clip.split(".").size() == 4)
                {
                    setText(clip);
                    return true;
                }
            }
        }
    }

    return QWidget::eventFilter(object, event);
}
  • input Output:
QString IPEdit::text()
{
    QString sec1 = m_edit1->text().isEmpty() ? "0" : m_edit1->text();
    QString sec2 = m_edit2->text().isEmpty() ? "0" : m_edit2->text();
    QString sec3 = m_edit3->text().isEmpty() ? "0" : m_edit3->text();
    QString sec4 = m_edit4->text().isEmpty() ? "0" : m_edit4->text();
    return QString("%1.%2.%3.%4").arg(sec1).arg(sec2).arg(sec3).arg(sec4);
}

void IPEdit::setText(const QString& text)
{
    QRegExp reg("^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$");
    if (!reg.exactMatch(text))
        return;
    
    QStringList ips = text.split(".");
    m_edit1->setText(ips.at(0));
    m_edit2->setText(ips.at(1));
    m_edit3->setText(ips.at(2));
    m_edit4->setText(ips.at(3));
}
  •  Style : In order to make the style consistent with the edit box, rewrite the drawing event:
void IPEdit::paintEvent(QPaintEvent* event)
{
    QPainter painter(this);

    QStyleOptionFrame option;
    option.initFrom(this);
    option.lineWidth = 1;
    style()->drawPrimitive(QStyle::PE_PanelLineEdit, &option, &painter, this);
    QWidget::paintEvent(event);
}

Customized (improved online)

I referred to the edit box of Windows' IP settings. Compared with the examples on the Internet, the effect is slightly different:

  • The focus switching of the tab key is different. The focus of each part of the online example (QLineEdit) responds to switching, but it does not happen under Windows;
  • The cursor position of the up, down, left and right keys can be spanned (adjacent to QLineEdit). There is no example on the Internet, but there is one under Windows;
  • Backspace (Qt::Key_Backspace) deletes the span.

I have improved these two aspects, the code is as follows:

  • Focus switching of the tab key: The edit box responds to the focus switching of the tab key and click (Qt::StrongFocus) by default, so I set all except the first edit box to click focus switching and no longer respond to the tab key focus switching.
    ui->lineEdit_2->setFocusPolicy(Qt::ClickFocus);
    ui->lineEdit_3->setFocusPolicy(Qt::ClickFocus);
    ui->lineEdit_4->setFocusPolicy(Qt::ClickFocus);

Movement of the cursor position using the up, down, left and right keys:

bool MyIpLinEdit::eventFilter(QObject *object, QEvent *event)
{
    if(object==ui->lineEdit||object==ui->lineEdit_2||object==ui->lineEdit_3||
       object==ui->lineEdit_4)
    {
        if (event->type() == QEvent::KeyPress)
        {
           QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
           if(keyEvent->key()==Qt::Key_Left||keyEvent->key()==Qt::Key_Up){
               cursorForwardPosition(static_cast<QLineEdit*>(object));
           }else if(keyEvent->key()==Qt::Key_Right||keyEvent->key()==Qt::Key_Down){
               cursorBackwardPosition(static_cast<QLineEdit*>(object));
           }
           
           ...   
  
        }
    }

    return QWidget::eventFilter(object, event);
}

void MyIpLinEdit::cursorBackwardPosition(QLineEdit *lineEdit)
{
    int pos=lineEdit->cursorPosition();
    int len=lineEdit->text().length();
    if(pos==len){
        QLineEdit* pDestLineEdit=nullptr;
        if(lineEdit==ui->lineEdit){
            pDestLineEdit=ui->lineEdit_2;

        }else if(lineEdit==ui->lineEdit_2){
            pDestLineEdit=ui->lineEdit_3;

        }else if(lineEdit==ui->lineEdit_3){
            pDestLineEdit=ui->lineEdit_4;

        }else if(lineEdit==ui->lineEdit_4){
            pDestLineEdit=ui->lineEdit;
        }
        pDestLineEdit->setFocus();
        pDestLineEdit->setCursorPosition(0);
    }
}

void MyIpLinEdit::cursorForwardPosition(QLineEdit *lineEdit)
{
    int pos=lineEdit->cursorPosition();
    if(pos==0){
        QLineEdit* pDestLineEdit=nullptr;
        if(lineEdit==ui->lineEdit){
            pDestLineEdit=ui->lineEdit_4;

        }else if(lineEdit==ui->lineEdit_2){
            pDestLineEdit=ui->lineEdit;

        }else if(lineEdit==ui->lineEdit_3){
            pDestLineEdit=ui->lineEdit_2;

        }else if(lineEdit==ui->lineEdit_4){
            pDestLineEdit=ui->lineEdit_3;
        }
        pDestLineEdit->setFocus();
        int len=pDestLineEdit->text().length();
        pDestLineEdit->setCursorPosition(len);
    }
}

 Backspace key:

bool MyIpLinEdit::eventFilter(QObject *object, QEvent *event)
{
      ....
      else if(keyEvent->key()==Qt::Key_Backspace){
               moveOfDeleteOnecharacter(qobject_cast<QLineEdit*>(object));

           }
      ....
}
void MyIpLinEdit::moveOfDeleteOnecharacter(QLineEdit *lineEdit)
{
    int len=lineEdit->text().length();
    if(len==0){
        QLineEdit* previous=previousEdit(lineEdit);
        if(previous){
            previous->setFocus();
            int len=previous->text().length();
            previous->setCursorPosition(len);
        }
    }
}
QLineEdit *MyIpLinEdit::previousEdit(QLineEdit *curEdit)
{
    if (curEdit == ui->lineEdit_2)
        return ui->lineEdit;
    else if (curEdit == ui->lineEdit_3)
        return ui->lineEdit_2;
    else if (curEdit == ui->lineEdit_4)
        return ui->lineEdit_3;
    else
        return NULL;
}

Source code

https://download.csdn.net/download/xiaopei_yan/87617065

Guess you like

Origin blog.csdn.net/xiaopei_yan/article/details/129789520