1、IP输入框组成
4个QLineEdit用于输入,3个QLabel用于显示小数点。
2、事件消息处理
installEventFilter捕获QLineEdit事件,重写eventFilter用于事件响应。
A、删除键Qt::Key_Backspace:若当前QLineEdit中光标左侧没有数据,则移到前一个QLineEdit中并删除一位;否则只删除一位。
B、左移键Qt::Key_Left:若当前QLineEdit中光标左侧没有数据,则移到前一个QLineEdit;否则只前移一位。
C、右移键Qt::Key_Right:若当前QLineEdit中光标右侧没有数据,则移到下一个QLineEdit;否则只后移一位。
D、英文小数点Qt::Key_Period:若当前QLineEdit不为空,则移到到下一个QLineEdit并全选;否则不移动。
E、中文句号:事件类型不是QEvent::KeyPress而是QEvent::InputMethod,判断数据数据是否含中文句号,若当前QLineEdit不为空,则移到到下一个QLineEdit并全选;否则不移动。
F、屏蔽QLineEdit右键菜单,处理Ctrl+V粘贴键盘事件。
3、代码
#ifndef QIPEdit_H
#define QIPEdit_H
#include <QWidget>
#include <QLineEdit>
#include <QLabel>
class QIPEdit : public QWidget
{
Q_OBJECT
public:
explicit QIPEdit(QWidget *parent = nullptr);
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
QString GetIP() const;
protected:
bool eventFilter(QObject *watched, QEvent *event) override;
private slots:
void textChanged(const QString &text);
public slots:
void clear();
bool setIP(const QString& strIP);
//设置背景颜色
void setBgColor(const QString &bgColor);
//设置边框颜色
void setBorderColor(const QString &borderColor);
//设置边框圆角角度
void setBorderRadius(int borderRadius);
private:
void setQss();
private:
QLabel* m_labelDot1;
QLabel* m_labelDot2;
QLabel* m_labelDot3;
QLineEdit* m_lineEditIP1;
QLineEdit* m_lineEditIP2;
QLineEdit* m_lineEditIP3;
QLineEdit* m_lineEditIP4;
QString m_strIP;
QString m_bgColor; //背景颜色
QString m_borderColor; //边框颜色
int m_borderRadius; //边框圆角角度
};
#endif // QIPEdit_H
#include "QIPEdit.h"
#include <QRegExp>
#include <QRegExpValidator>
#include <QApplication>
#include <QClipboard>
#include <QLayout>
#include <QEvent>
#include <QKeyEvent>
#include <QDebug>
QIPEdit::QIPEdit(QWidget *parent) : QWidget(parent)
{
m_bgColor = "#FFFFFF";
m_borderColor = "#A6B5B8";
m_borderRadius = 10;
m_labelDot1 = new QLabel(this);
m_labelDot1->setAlignment(Qt::AlignCenter);
m_labelDot1->setText(".");
m_labelDot2 = new QLabel(this);
m_labelDot2->setAlignment(Qt::AlignCenter);
m_labelDot2->setText(".");
m_labelDot3 = new QLabel(this);
m_labelDot3->setAlignment(Qt::AlignCenter);
m_labelDot3->setText(".");
m_lineEditIP1 = new QLineEdit;
m_lineEditIP1->setObjectName("lineEditIP1");
m_lineEditIP1->setAlignment(Qt::AlignCenter);
m_lineEditIP1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
connect(m_lineEditIP1, SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
m_lineEditIP2 = new QLineEdit;
m_lineEditIP2->setObjectName("lineEditIP2");
m_lineEditIP2->setAlignment(Qt::AlignCenter);
m_lineEditIP2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
connect(m_lineEditIP2, SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
m_lineEditIP3 = new QLineEdit;
m_lineEditIP3->setObjectName("lineEditIP3");
m_lineEditIP3->setAlignment(Qt::AlignCenter);
m_lineEditIP3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
connect(m_lineEditIP3, SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
m_lineEditIP4 = new QLineEdit;
m_lineEditIP4->setObjectName("lineEditIP4");
m_lineEditIP4->setAlignment(Qt::AlignCenter);
m_lineEditIP4->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
connect(m_lineEditIP4, SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
QRegExp regExp("(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)");
QRegExpValidator *validator = new QRegExpValidator(regExp, this);
m_lineEditIP1->setValidator(validator);
m_lineEditIP2->setValidator(validator);
m_lineEditIP3->setValidator(validator);
m_lineEditIP4->setValidator(validator);
m_lineEditIP1->setContextMenuPolicy(Qt::NoContextMenu);
m_lineEditIP2->setContextMenuPolicy(Qt::NoContextMenu);
m_lineEditIP3->setContextMenuPolicy(Qt::NoContextMenu);
m_lineEditIP4->setContextMenuPolicy(Qt::NoContextMenu);
m_lineEditIP1->installEventFilter(this);
m_lineEditIP2->installEventFilter(this);
m_lineEditIP3->installEventFilter(this);
m_lineEditIP4->installEventFilter(this);
QFrame *frame = new QFrame(this);
frame->setObjectName("frameIP");
setQss();
QVBoxLayout *verticalLayout = new QVBoxLayout(this);
verticalLayout->setMargin(0);
verticalLayout->setSpacing(0);
verticalLayout->addWidget(frame);
QHBoxLayout *layout = new QHBoxLayout(frame);
layout->setMargin(0);
layout->setSpacing(0);
layout->addWidget(m_lineEditIP1);
layout->addWidget(m_labelDot1);
layout->addWidget(m_lineEditIP2);
layout->addWidget(m_labelDot2);
layout->addWidget(m_lineEditIP3);
layout->addWidget(m_labelDot3);
layout->addWidget(m_lineEditIP4);
}
QSize QIPEdit::sizeHint() const
{
return QSize(250, 30);
}
QSize QIPEdit::minimumSizeHint() const
{
return QSize(50,30);
}
QString QIPEdit::GetIP() const
{
if(m_lineEditIP1->text().isEmpty() || m_lineEditIP2->text().isEmpty() ||
m_lineEditIP3->text().isEmpty() || m_lineEditIP4->text().isEmpty())
{
return "";
}
return m_strIP;
}
bool QIPEdit::eventFilter(QObject *watched, QEvent *event)
{
QLineEdit* lineEditIP = qobject_cast<QLineEdit*>(watched);
if(lineEditIP)
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Period) //如果当前按下了小数点则移动焦点到下一个输入框
{
if(!lineEditIP->text().isEmpty()) //文本框不为空时后移
{
this->focusNextChild();
QLineEdit* lineEditNext = qobject_cast<QLineEdit*>(focusWidget());
lineEditNext->selectAll();
}
}
else if (keyEvent->key() == Qt::Key_Backspace && lineEditIP->cursorPosition() == 0 ) //如果当前按下了小数点则移动焦点到下一个输入框
{
if(lineEditIP != m_lineEditIP1 && focusNextPrevChild(false))
{
QLineEdit* lineEditPrev = qobject_cast<QLineEdit*>(focusWidget());
lineEditPrev->setCursorPosition(lineEditPrev->text().size());
lineEditPrev->backspace();
}
}
else if(keyEvent->key() == Qt::Key_Left && lineEditIP->cursorPosition() == 0)
{
if(lineEditIP != m_lineEditIP1 && focusNextPrevChild(false))
{
QLineEdit* lineEditPrev = qobject_cast<QLineEdit*>(focusWidget());
lineEditPrev->setCursorPosition(lineEditPrev->text().size());
}
}
else if(keyEvent->key() == Qt::Key_Right && lineEditIP->cursorPosition() == lineEditIP->text().size())
{
if(lineEditIP != m_lineEditIP4 && focusNextPrevChild(true))
{
QLineEdit* lineEditNext = qobject_cast<QLineEdit*>(focusWidget());
lineEditNext->setCursorPosition(0);
}
return false;
}
else if (keyEvent->matches(QKeySequence::Paste))
{
QClipboard* clipBoard = QApplication::clipboard();
QString strIP = clipBoard->text();
setIP(strIP);
return false;
}
}
else if (event->type() == QEvent::InputMethod)
{
QInputMethodEvent* inputMethodEvent = static_cast<QInputMethodEvent*>(event);
QString strText = inputMethodEvent->commitString();
QString strText2 = inputMethodEvent->preeditString();
qDebug()<<strText << "11111" << strText2;
if(strText.contains("。") && !lineEditIP->text().isEmpty())
{
this->focusNextChild();
QLineEdit* lineEditNext = qobject_cast<QLineEdit*>(focusWidget());
lineEditNext->selectAll();
}
}
}
return QWidget::eventFilter(watched, event);
}
void QIPEdit::clear()
{
m_lineEditIP1->clear();
m_lineEditIP2->clear();
m_lineEditIP3->clear();
m_lineEditIP4->clear();
m_lineEditIP1->setFocus();
}
bool QIPEdit::setIP(const QString &strIP)
{
//先检测IP地址是否合法
QRegExp regExp("((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)");
if (!regExp.exactMatch(strIP))
{
return false;
}
if (strIP != m_strIP)
{
m_strIP = strIP;
//将IP地址填入各个网段
QStringList list = m_strIP.split(".");
m_lineEditIP1->setText(list.at(0));
m_lineEditIP2->setText(list.at(1));
m_lineEditIP3->setText(list.at(2));
m_lineEditIP4->setText(list.at(3));
m_lineEditIP4->setFocus();
m_lineEditIP4->setCursorPosition(m_lineEditIP4->text().size());
}
return true;
}
void QIPEdit::setBgColor(const QString &bgColor)
{
if(m_bgColor != bgColor)
{
m_bgColor = bgColor;
setQss();
}
}
void QIPEdit::setBorderColor(const QString &borderColor)
{
if(m_borderColor != borderColor)
{
m_borderColor = borderColor;
setQss();
}
}
void QIPEdit::setBorderRadius(int borderRadius)
{
if(m_borderRadius != borderRadius)
{
m_borderRadius = borderRadius;
setQss();
}
}
void QIPEdit::setQss()
{
QStringList qss;
qss.append(QString("QFrame#frameIP{border:1px solid %1;border-radius:%2px;}").arg(m_borderColor).arg(m_borderRadius));
qss.append(QString("QLabel{min-width:15px;background-color:%1;}").arg(m_bgColor));
qss.append(QString("QLineEdit{background-color:%1;border:none;}").arg(m_bgColor));
qss.append(QString("QLineEdit#lineEditIP1{border-top-left-radius:%1px;border-bottom-left-radius:%1px;}").arg(m_borderRadius));
qss.append(QString("QLineEdit#lineEditIP4{border-top-right-radius:%1px;border-bottom-right-radius:%1px;}").arg(m_borderRadius));
setStyleSheet(qss.join(""));
}
void QIPEdit::textChanged(const QString &text)
{
int len = text.length();
int value = text.toInt();
if (len == 3)
{
if (value >= 100 && value <= 255)
{
this->focusNextChild();
}
}
m_strIP = QString("%1.%2.%3.%4").arg(m_lineEditIP1->text().toInt()).arg(m_lineEditIP2->text().toInt()).
arg(m_lineEditIP3->text().toInt()).arg(m_lineEditIP4->text().toInt());
qDebug()<<"IP:"<<m_strIP;
}