Qt编写自定义IP地址控件

在日常开发过程中,Qt给我们提供的基础控件往往满足不了一些复杂的开发项目,许多精巧的小控件是需要我们自己去基于一些原生控件去自定义编写的,这也是Qt开发中的一项重要技能。比如我们在开发网络程序的过程中,需要经常性的输入源地址和目标地址的IP,而Qt designer并未给我们提供IP地址输入控件(印象中MFC中有此控件),此时就需要我们自己去自定义编写,经过本人的研究,在此贡献一套自己编写好的控件代码:

MyIpPartLineEdit.h
 1 #pragma once
 2 #include <QLineEdit>   
 3 class QWidget;
 4 class QFocusEvent;
 5 class QKeyEvent;
 6 
 7 class MyIpPartLineEdit : public QLineEdit
 8 {
 9     Q_OBJECT
10 public:
11     MyIpPartLineEdit(QWidget *parent = 0);
12     ~MyIpPartLineEdit(void);
13 
14     void set_prevtab_edit(QLineEdit *currenttab, QLineEdit *prevtab) { current_tab_ = currenttab, prev_tab_ = prevtab; }
15     void set_nexttab_edit(QLineEdit *currenttab, QLineEdit *nexttab) {current_tab_ = currenttab, next_tab_ = nexttab; }
16 
17     //void 
18 
19 protected:
20     virtual void focusInEvent(QFocusEvent *e);
21     virtual    void keyPressEvent(QKeyEvent *event);
22 
23     private slots:
24     void text_edited(const QString& text);
25 
26 private:
27     QLineEdit *current_tab_, *prev_tab_, *next_tab_;
28 };
MyIpPartLineEdit.cpp
#include "MyIpPartLineEdit.h"   
#include <QIntValidator>   
#include <QKeyEvent>   

MyIpPartLineEdit::MyIpPartLineEdit(QWidget *parent/* = 0*/)
    : QLineEdit(parent)
{
    next_tab_ = NULL;
    prev_tab_ = NULL;

    this->setMaxLength(3);
    this->setFrame(false);
    this->setAlignment(Qt::AlignCenter);

    QValidator *validator = new QIntValidator(0, 255, this);
    this->setValidator(validator);

    connect(this, SIGNAL(textEdited(const QString&)), this, SLOT(text_edited(const QString&)));
}

MyIpPartLineEdit::~MyIpPartLineEdit(void)
{
}

void MyIpPartLineEdit::focusInEvent(QFocusEvent *e)
{
    this->selectAll();
    QLineEdit::focusInEvent(e);
}

void MyIpPartLineEdit::keyPressEvent(QKeyEvent *event)
{

    if (event->key() == Qt::Key_Period)
    {
        QString current_tab = current_tab_->text();
        if (next_tab_  && (!current_tab.isEmpty()))
        {
            next_tab_->setFocus();
            next_tab_->selectAll();
        }
    }
    else if (event->key() == Qt::Key_Backspace)
    {
        QString current_tab = current_tab_->text();
        if (prev_tab_ && (current_tab.isEmpty()))
        {
            prev_tab_->setFocus();
            prev_tab_->selectAll();
        }
    }

    QLineEdit::keyPressEvent(event);
}

void MyIpPartLineEdit::text_edited(const QString& text)
{
    QIntValidator v(0, 255, this);
    QString ipaddr = text;
    int pos = 0;
    QValidator::State state = v.validate(ipaddr, pos);
    if (state == QValidator::Acceptable)
    {
        if (ipaddr.size() > 1)
        {
            if (ipaddr.size() == 2)
            {
                int ipnum = ipaddr.toInt();

                if (ipnum > 25)
                {
                    if (next_tab_)
                    {
                        next_tab_->setFocus();
                        next_tab_->selectAll();
                    }
                }
            }
            else
            {
                if (next_tab_)
                {
                    next_tab_->setFocus();
                    next_tab_->selectAll();
                }
            }
        }
    }
}
MyIpAddrEdit.h
#include <QWidget>  

class QLineEdit;
class QLabel;
class MyIpPartLineEdit;

class MyIpAddrEdit : public QWidget
{
    Q_OBJECT
public:
    MyIpAddrEdit(QWidget* pParent = 0);
    ~MyIpAddrEdit();

    void settext(const QString &text);
    QString text();
    void getIp(QString& ip1, QString& ip2, QString& ip3, QString& ip4);
    void setStyleSheet(const QString &styleSheet);

signals:
    void textchanged(const QString& text);
    void textedited(const QString &text);

    private slots:
    void textchangedslot(const QString& text);
    void texteditedslot(const QString &text);

private:
    MyIpPartLineEdit *ip_part1_;
    MyIpPartLineEdit *ip_part2_;
    MyIpPartLineEdit *ip_part3_;
    //QLineEdit *ip_part4_;
    MyIpPartLineEdit *ip_part4_;

    QLabel *labeldot1_;
    QLabel *labeldot2_;
    QLabel *labeldot3_;
};
MyIpAddrEdit.cpp
#include "MyIpAddrEdit.h"   
#include <QRegExpValidator>   
#include <QLabel>   
#include "MyIpPartLineEdit.h"
#include "qjsondocument.h"

MyIpAddrEdit::MyIpAddrEdit(QWidget* pParent /* = 0 */)
    : QWidget(pParent)
{
    QFont font(".萍方-简", 10);
    ip_part1_ = new MyIpPartLineEdit(this);
    ip_part2_ = new MyIpPartLineEdit(this);
    ip_part3_ = new MyIpPartLineEdit(this);
    ip_part4_ = new MyIpPartLineEdit(this);

    labeldot1_ = new QLabel(this);
    labeldot2_ = new QLabel(this);
    labeldot3_ = new QLabel(this);

    ip_part1_->setGeometry(QRect(0,  0, 44, 28));
    ip_part2_->setGeometry(QRect(44, 0, 44, 28));
    ip_part3_->setGeometry(QRect(88, 0, 44, 28));
    ip_part4_->setGeometry(QRect(132,0, 44, 28));

    ip_part1_->setFont(font);
    ip_part2_->setFont(font);
    ip_part3_->setFont(font);
    ip_part4_->setFont(font);

    labeldot1_->setText(" .");
    labeldot1_->setFont(font);
    labeldot1_->setGeometry(QRect(41, 5, 6, 18));
    labeldot1_->setAlignment(Qt::AlignCenter);

    labeldot2_->setText(" .");
    labeldot2_->setFont(font);
    labeldot2_->setGeometry(QRect(85, 5, 6, 18));
    labeldot2_->setAlignment(Qt::AlignCenter);

    labeldot3_->setText(" .");
    labeldot3_->setFont(font);
    labeldot3_->setGeometry(QRect(129, 5, 6, 18));
    labeldot3_->setAlignment(Qt::AlignCenter);

    QWidget::setTabOrder(ip_part1_, ip_part2_);//定义切换焦点顺序
    QWidget::setTabOrder(ip_part2_, ip_part3_);
    QWidget::setTabOrder(ip_part3_, ip_part4_);

    ip_part1_->set_nexttab_edit(ip_part1_, ip_part2_);
    ip_part2_->set_nexttab_edit(ip_part2_, ip_part3_);
    ip_part3_->set_nexttab_edit(ip_part3_, ip_part4_);

    ip_part2_->set_prevtab_edit(ip_part2_, ip_part1_);
    ip_part3_->set_prevtab_edit(ip_part3_, ip_part2_);
    ip_part4_->set_prevtab_edit(ip_part4_, ip_part3_);

    connect(ip_part1_, SIGNAL(textChanged(const QString&)), this, SLOT(textchangedslot(const QString&)));
    connect(ip_part2_, SIGNAL(textChanged(const QString&)), this, SLOT(textchangedslot(const QString&)));
    connect(ip_part3_, SIGNAL(textChanged(const QString&)), this, SLOT(textchangedslot(const QString&)));
    connect(ip_part4_, SIGNAL(textChanged(const QString&)), this, SLOT(textchangedslot(const QString&)));

    connect(ip_part1_, SIGNAL(textEdited(const QString&)), this, SLOT(texteditedslot(const QString&)));
    connect(ip_part2_, SIGNAL(textEdited(const QString&)), this, SLOT(texteditedslot(const QString&)));
    connect(ip_part3_, SIGNAL(textEdited(const QString&)), this, SLOT(texteditedslot(const QString&)));
    connect(ip_part4_, SIGNAL(textEdited(const QString&)), this, SLOT(texteditedslot(const QString&)));

}

MyIpAddrEdit::~MyIpAddrEdit()
{

}

void MyIpAddrEdit::textchangedslot(const QString& /*text*/)
{
    QString ippart1, ippart2, ippart3, ippart4;
    ippart1 = ip_part1_->text();
    ippart2 = ip_part2_->text();
    ippart3 = ip_part3_->text();
    ippart4 = ip_part4_->text();

    QString ipaddr = QString("%1.%2.%3.%4")
        .arg(ippart1)
        .arg(ippart2)
        .arg(ippart3)
        .arg(ippart4);

    emit textchanged(ipaddr);
}

void MyIpAddrEdit::texteditedslot(const QString &/*text*/)
{
    QString ippart1, ippart2, ippart3, ippart4;
    ippart1 = ip_part1_->text();
    ippart2 = ip_part2_->text();
    ippart3 = ip_part3_->text();
    ippart4 = ip_part4_->text();

    QString ipaddr = QString("%1.%2.%3.%4")
        .arg(ippart1)
        .arg(ippart2)
        .arg(ippart3)
        .arg(ippart4);

    emit textedited(ipaddr);
}

void MyIpAddrEdit::settext(const QString &text)
{
    QString ippart1, ippart2, ippart3, ippart4;
    QString qstring_validate = text;

    // IP地址验证   
    QRegExp regexp("((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)");
    QRegExpValidator regexp_validator(regexp, this);
    int nPos = 0;
    QValidator::State state = regexp_validator.validate(qstring_validate, nPos);
    // IP合法   
    if (state == QValidator::Acceptable)
    {
        QStringList ippartlist = text.split(".");

        int strcount = ippartlist.size();
        int index = 0;
        if (index < strcount)
        {
            ippart1 = ippartlist.at(index);
        }
        if (++index < strcount)
        {
            ippart2 = ippartlist.at(index);
        }
        if (++index < strcount)
        {
            ippart3 = ippartlist.at(index);
        }
        if (++index < strcount)
        {
            ippart4 = ippartlist.at(index);
        }
    }

    ip_part1_->setText(ippart1);
    ip_part2_->setText(ippart2);
    ip_part3_->setText(ippart3);
    ip_part4_->setText(ippart4);
}

QString MyIpAddrEdit::text()
{
    QString ippart1, ippart2, ippart3, ippart4;
    ippart1 = ip_part1_->text();
    ippart2 = ip_part2_->text();
    ippart3 = ip_part3_->text();
    ippart4 = ip_part4_->text();

    return QString("%1.%2.%3.%4")
        .arg(ippart1)
        .arg(ippart2)
        .arg(ippart3)
        .arg(ippart4);
}

void MyIpAddrEdit::getIp(QString& ip1, QString& ip2, QString& ip3, QString& ip4)
{
    ip1 = ip_part1_->text();
    ip2 = ip_part2_->text();
    ip3 = ip_part3_->text();
    ip4 = ip_part4_->text();
}

void MyIpAddrEdit::setStyleSheet(const QString &styleSheet)
{
    ip_part1_->setStyleSheet(styleSheet);
    ip_part2_->setStyleSheet(styleSheet);
    ip_part3_->setStyleSheet(styleSheet);
    ip_part4_->setStyleSheet(styleSheet);
}

在工程中添加上述C++文件后,便可以使用,使用方法如下:

在工程类头文件中声明 IP 地址类 成员变量:

![]()

<br></br>在使用前对其进行初始化(一般在项目构造函数中):<br></br>此处在下是直接将其添加进入一个水平布局中,大家使用的时候可以随意。

![]()

<strong>方法调用:</strong>
m_objIpAddrEdit->settext(p_ip);     //设置IP地址(也可以手动输入)
QString p_ip = m_objIpAddrEdit->text();    //获取IP地址
QString p_ip1, p_ip2, p_ip3, p_ip4, p_ip;  
m_objIpAddrEdit->getIp(p_ip1, p_ip2, p_ip3, p_ip4); //获取IP地址的四个部分
//判断IP输入是否合法
 if (p_ip1 == NULL || p_ip2 == NULL || p_ip3 == NULL || p_ip4 == NULL)
{
    strMessage = tr("IP settings are illegal, please reenter it!\n");
    qBox.setText(strMessage);
    switch (qBox.exec())
    {
    case QMessageBox::Yes:
        {
            return;
        }
    }
}   

运行效果:

![]()

ok,我想我说的已经很明了了,希望能够帮助到各位。

声明:该文章系转载,转载该文章的目的在于更广泛的传递信息,并不代表本网站赞同其观点,文章内容仅供参考。

本站是一个个人学习和交流平台,网站上部分文章为网站管理员和网友从相关媒体转载而来,并不用于任何商业目的,内容为作者个人观点, 并不代表本网站赞同其观点和对其真实性负责。

我们已经尽可能的对作者和来源进行了通告,但是可能由于能力有限或疏忽,导致作者和来源有误,亦可能您并不期望您的作品在我们的网站上发布。我们为这些问题向您致歉,如果您在我站上发现此类问题,请及时联系我们,我们将根据您的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。