在日常开发过程中,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 地址类 成员变量:

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

方法调用:
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,我想我说的已经很明了了,希望能够帮助到各位。
