IP 編集ボックス (公式、オンライン、カスタム) - QtWidget

序文

最近はガジェットインターフェース上にIP編集ボックスが使われていますが、現在は編集ボックスQLineEditを直接配置していますが、個人利用なのであまり制限を書く必要はありません。ただし、時間に余裕がある場合は、公式のもの (つまり、QLineEdit に基づいて直接セットアップ)、オンラインのもの (QLineEdit によって接続されたもの)、およびカスタマイズされたもの (オンラインのものと自己改善) を使用してみてください。

効果

成し遂げる

公式 (単一の QLineEdit)

公式には単一の QLineEdit 上で正規表現とマスクを直接設定する方法があり、コードは次のとおりですが、効果はあまり良くありません。

  • カーソルは太くて黒く、単一の文字を選択して変更するモードに属します。
  • コンテンツがボックス全体に散らばっておらず、配置を中央に変更しても左に変更しても見栄えがよくありません。
  • また、プレースホルダーをスペースにすると、今の数字が何番か分からなくなるので、2番目の数字を選択して「192」と入力すると、そのまま「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; ");

正規表現における各記号の説明: 

  • \d: [0-9] に相当する数値と一致します。
  • \.: 小数点と一致します
  • ?: 前の内容を 0 回または 1 回繰り返すことを示します
  • 2[0-4]\\d: 200 ~ 249 の値をカバーします
  • 25[0-5]: 250 ~ 255 の値をカバーします
  • [01]?\\d\\d?:0~199の値をカバーします

正規表現オンライン テスト ツール:正規表現オンライン テスト | ルーキー ツール

オンライン (複数の QLineEdit スプライシング)

github で見つけたアドレスは次のとおりです: https://github.com/KingBright965/QtIPEdit/blob/master/IPEdit.cpp

  • 全体とコンテンツの制御: 複数の QLineEdit と QLabel で構成され、各 QLineEdit は正規表現で設定され、同時に各部分の最大長を 3 に制御するために、エディット ボックスのコンテンツ編集を監視します現在の長さは 3 なので、次の編集ボックスに移動します。
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();
        }
    }
}
  •  イベント応答: イベント フィルタリング、キー ポイント (Qt::Key_Period) の監視、イベントの貼り付け (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);
}
  • 入出力:
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));
}
  •  スタイル: スタイルを編集ボックスと一致させるために、描画イベントを書き換えます。
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);
}

カスタマイズ(オンラインで改善)

Windows の IP 設定のエディットボックスを参考にしましたが、インターネット上の例と比較すると、効果が若干異なります。

  • タブキーのフォーカス切り替えが異なり、オンラインサンプル(QLineEdit)では各部のフォーカスが切り替わりますが、Windowsでは切り替わりません。
  • 上下左右キーのカーソル位置をまたがることができます (QLineEdit に隣接) インターネット上には例がありませんが、Windows では例があります。
  • バックスペース (Qt::Key_Backspace) はスパンを削除します。

これら 2 つの側面を改善しました。コードは次のとおりです。

  • タブキーのフォーカス切り替え:エディットボックスはデフォルトでタブキーのフォーカス切り替えとクリック(Qt::StrongFocus)に反応するので、最初のエディットボックス以外はすべてクリックフォーカス切り替えに設定し、タブには反応しなくなりましたキーフォーカスの切り替え。
    ui->lineEdit_2->setFocusPolicy(Qt::ClickFocus);
    ui->lineEdit_3->setFocusPolicy(Qt::ClickFocus);
    ui->lineEdit_4->setFocusPolicy(Qt::ClickFocus);

上下左右キーを使用したカーソル位置の移動:

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);
    }
}

 バックスペースキー:

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;
}

ソースコード

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

おすすめ

転載: blog.csdn.net/xiaopei_yan/article/details/129789520