QT没有提供完整的IP输入框,如果只用正则表达式和LineEdit不可能实现像Windows下那样的IP输入框。于是我便在网上百度到可以使用四个LineEdit和三个Label可以实现像Windows下那样的IP输入框。网上的几乎都是一个界面中只有IP的输入框,可是由于项目要求我的一个界面不可能只有IP输入框。于是便花了我差不多快一个星期的时间(花的时间有点长)终于实现了我想要的效果。
流程图:
我首先在xx.ui界面中画了四个LineEdit(分别取名为(le_ip_1,le_ip_2,le_ip_3,le_ip_4)做输入IP地址用,限定了最大输入长度为3)三个Label(输入点)最外面的框是一个容器Frame
代码:
xx.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QRegExp>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//设置lineEdit的边框隐藏
ui->le_ip_1->setFrame(false);
ui->le_ip_2->setFrame(false);
ui->le_ip_3->setFrame(false);
ui->le_ip_4->setFrame(false);
//安装事件过滤器
ui->le_ip_1->installEventFilter(this);
ui->le_ip_2->installEventFilter(this);
ui->le_ip_3->installEventFilter(this);
ui->le_ip_4->installEventFilter(this);
//正则表达式,为了实现每输入两个字节如果错误就能提示
QRegExp rx ( "^([0-9]{1,3})$" );
QValidator *validator = new QRegExpValidator(rx, this);
ui->le_ip_1->setValidator( validator );
ui->le_ip_2->setValidator( validator);
ui->le_ip_3->setValidator( validator);
ui->le_ip_4->setValidator( validator );
connect( this, SIGNAL(signalTextChanged(QLineEdit*)),this, SLOT(slotTextChanged(QLineEdit*)),Qt::QueuedConnection );
connect(ui->le_ip_1,SIGNAL(textChanged(QString)),this,SLOT(lineEditChanged()));
connect(ui->le_ip_2,SIGNAL(textChanged(QString)),this,SLOT(lineEditChanged()));
connect(ui->le_ip_3,SIGNAL(textChanged(QString)),this,SLOT(lineEditChanged()));
connect(ui->le_ip_4,SIGNAL(textChanged(QString)),this,SLOT(lineEditChanged()));
}
void MainWindow::lineEditChanged()
{
//为了判断是哪个LineEdit发出信号
QLineEdit *pEdit = qobject_cast<QLineEdit *>(sender());
if(pEdit->text().size() == 3 && pEdit->text().size() == pEdit->cursorPosition())
{
moveNextLine(pdit);
}
}
void MainWindow::slotTextChanged(QLineEdit *pEdit)
{
if(pEdit->text().size() == 3 && pEdit->text().size() == pEdit->cursorPosition())
{
moveNextLine(pdit);
}
}
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
bool bRes = QWidget::eventFilter(obj,event);
if(obj == ui->le_ip_1 || obj == ui->le_ip_2 || obj == ui->le_ip_3 || obj == ui->le_ip_4)
{
if(event->type() == QEvent::KeyPress)
{
QKeyEvent * pEvent = dynamic_cast<QKeyEvent *>(event);
QLineEdit* pdit = qobject_cast<QLineEdit*>(obj);
if(pdit == ui->le_ip_1||pdit == ui->le_ip_2||pdit == ui->le_ip_3 || pdit == ui->le_ip_4)
{
switch(pEvent->key())
{
case Qt::Key_Left:
if(pdit->cursorPosition()==0)
{
movePreLine( pdit);
}
break;
case Qt::Key_Right:
if(pdit->text().isEmpty()||(pdit->text().size() == pdit->cursorPosition()))
{
moveNextLine(pdit);
}
break;
case Qt::Key_0:
if(pdit->text().isEmpty()||pdit->text() == "0")
{
pdit->setText("000");
moveNextLine(pdit);
}
emit signalTextChanged(pdit);
break;
case::Qt::Key_Backspace:
if(pdit->text().isEmpty()||pdit->cursorPosition() == 0)
{
movePreLine( pdit);
}
break;
case Qt::Key_Comma:
case Qt::Key_Period:
moveNextLine(pdit);
break;
default:
emit signalTextChanged(pdit);
break;
}
}
}
}
return bRes;
}
void MainWindow:: moveNextLine(QLineEdit * pdit)
{
if(pdit != ui->le_ip_4)
{
if(pdit == ui->le_ip_1)
{
ui->le_ip_2->setFocus();
ui->le_ip_2->selectAll();
ui->le_ip_2->setCursorPosition(0);
}
else if(pdit == ui->le_ip_2)
{
ui->le_ip_3->setFocus();
ui->le_ip_3->selectAll();
ui->le_ip_3->setCursorPosition(0);
}
else if(pdit ==ui->le_ip_3)
{
ui->le_ip_4->setFocus();
ui->le_ip_4->selectAll();
ui->le_ip_4->setCursorPosition(0);
}
}
}
void MainWindow::movePreLine(QLineEdit * pdit)
{
if(pdit != ui->le_ip_1)
{
if(pdit == ui->le_ip_2)
{
ui->le_ip_1->setFocus();
ui->le_ip_1->setCursorPosition(ui->le_ip_1->text().size());
}
else if(pdit == ui->le_ip_3)
{
ui->le_ip_2->setFocus();
ui->le_ip_2->setCursorPosition(ui->le_ip_2->text().size());
}
else if(pdit ==ui->le_ip_4)
{
ui->le_ip_3->setFocus();
ui->le_ip_3->setCursorPosition(ui->le_ip_3->text().size());
}
}
}
void MainWindow::on_le_ip_1_editingFinished()
{
QString ipaddr = ui->le_ip_1->text();
int ipnum;
ipnum = ipaddr.toInt();
if(ipnum == 127)
{
ui->le_ip_1->setText("1");
QMessageBox::warning(this,tr("warning"),tr("以127开头的是无效地址,为环回地址,请输入1~223之间的其他数"));
}
if(ipnum >223)
{
ui->le_ip_1->setText("223");
QMessageBox::warning(this,tr("warning"),tr("请输入1~223之间的数"));
}
}
void MainWindow::on_le_ip_2_editingFinished()
{
QString ipaddr = ui->le_ip_2->text();
int ipnum;
ipnum = ipaddr.toInt();
if(ipnum >255)
{
ui->le_ip_2->setText("255");
QMessageBox::warning(this,tr("warning"),tr("请输入0~255之间的数"));
}
}
void MainWindow::on_le_ip_3_editingFinished()
{
QString ipaddr = ui->le_ip_3->text();
int ipnum;
ipnum = ipaddr.toInt();
if(ipnum >255)
{
ui->le_ip_3->setText("255");
QMessageBox::warning(this,tr("warning"),tr("请输入0~255之间的数"));
}
}
xx.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "ui_mainwindow.h"
#include <QMainWindow>
#include <QWidget>
#include <QLabel>
#include <QLineEdit>
#include <QKeyEvent>
#include <QIntValidator>
#define MAX 100
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void movePreLine(QLineEdit* pdit);
void moveNextLine(QLineEdit* pdit);
virtual bool eventFilter(QObject *obj, QEvent *event);
public slots:
void slotTextChanged(QLineEdit *pEdit);
void lineEditChanged();
signals:
void signalTextChanged(QLineEdit *pEdit);
private slots:
void on_le_ip_1_editingFinished();
void on_le_ip_2_editingFinished();
void on_le_ip_3_editingFinished();
void on_le_ip_4_editingFinished();
void on_le_ip_4_returnPressed();
void on_le_ip_4_textEdited();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
参考博客:https://blog.csdn.net/ganggegel/article/details/78644919?utm_source=app
https://blog.csdn.net/u013625961/article/details/76854559?utm_source=app
遇到的问题:
1.不同框之间焦点的跳转
由于我百度到的都是将几个LineEdit都是将它们加到一个指针数组或者将LineEdit提升为一个类,而我的几个LineEdit是在ui界面中画好的,如果提升为一个类,可我的界面中不可能只有IP输入框,所以将会很麻烦,我也想过将它们加到指针数组中,可打印出的地址是同一个,老是不对,后来百度到原来在ui界面中画好的不能将它们加到指针数组中。
解决方法:只能采取笨办法判断是哪个lineedit发出信号再做相应的操作,虽然实现了相应的功能,但代码有点冗余,有待改进。
2.正则表达式模块
我想实现的是每输入两个字节如果出错就能够弹出提示框输入出错,可如果采用以下代码,它只是对你的输入做出了限制,出错了只会不显示在编辑框中。
QRegExp rx ( "^(0|[1-9]|[1-9][0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))$" );
QValidator *validator = new QRegExpValidator(rx, pEdit);
pEdit->setValidator( validator );
解决方法:将rx中的限制改为( "^([0-9]{1,3})$" );
然后再在每个输入框编辑完成时对其中的文本进行判断是否合法
3.事件过滤器模块
由于我前面没有使用指针数组或将lineedit提升为一个类,所以我不能直接得到ui界面中对象,只能得到对象名。
解决方法:
QLineEdit* pdit = qobject_cast<QLineEdit*>(obj);
这时就可以根据pdit来判断是ui界面中的哪个对象