其实Qt的QLineEdit已经提供了setInputMask函数可以直接使用,只是为了学习自定义控件。
我们知道实现自定义控件有三种方式:
1.使用自绘
此处不是很适合,需要我们自绘光标、计算位置信息等增加代码量。
2.使用控件组合
如果使用组合控件实现,我们需要4个QLineEdit和3个QLable。明显增加了控件数量。程序效率不高。
3.继承QLineEdit实现virtual方法
在这里比较适合,减少了我们工作量。我们不用手动实现位置计算,光标位置控制等。
ip_input.h 定义如下:
#ifndef IP_INPUT_H
#define IP_INPUT_H
#include <QLineEdit>
#include <QWidget>
#include <QString>
#include <QSize>
class IpInput : public QLineEdit
{
Q_OBJECT
public:
IpInput(QWidget *parent = nullptr);
~IpInput() = default;
protected:
virtual void keyPressEvent(QKeyEvent *event) override;
void showIp();
virtual QSize sizeHint() const;
private:
QString ip1;
QString ip2;
QString ip3;
QString ip4;
int pos = 3;
};
#endif // IP_INPUT_H
ip_input.cpp 实现如下:
#include "ip_input.h"
#include <QPainter>
#include <QDebug>
#include <QFontMetrics>
#include <QRect>
#include <QKeyEvent>
#include <QLatin1Char>
IpInput::IpInput(QWidget *parent) : QLineEdit(parent)
{
setAlignment(Qt::AlignCenter);
showIp();
}
void IpInput::keyPressEvent(QKeyEvent *event)
{
if (event->type() == QEvent::KeyPress) {
switch (event->key()) {
case Qt::Key_0:
case Qt::Key_1:
case Qt::Key_2:
case Qt::Key_3:
case Qt::Key_4:
case Qt::Key_5:
case Qt::Key_6:
case Qt::Key_7:
case Qt::Key_8:
case Qt::Key_9: {
if (cursorPosition() == 3) {
QString temp = ip1 + event->text();
if (temp.toInt() > 255) {
pos = 7;
} else {
if (temp.length() >= 3) {
temp = temp.right(3);
}
ip1 = temp;
}
}
if (cursorPosition() == 7) {
QString temp = ip2 + event->text();
if (temp.toInt() > 255) {
pos = 11;
} else {
ip2 = temp;
}
}
if (cursorPosition() == 11) {
QString temp = ip3 + event->text();
if (temp.toInt() > 255) {
pos = 15;
} else {
ip3 = temp;
}
}
if (cursorPosition() == 15) {
QString temp = ip4 + event->text();
if (temp.toInt() > 255) {
pos = 15;
} else {
ip4 = temp;
}
}
showIp();
event->accept();
break;
}
break;
case Qt::Key_Right:
if (cursorPosition() == 3) {
pos = 7;
} else if(cursorPosition() == 7) {
pos = 11;
} else if(cursorPosition() == 11) {
pos = 15;
} else if(cursorPosition() == 15) {
return;
}
showIp();
break;
case Qt::Key_Left:
if (cursorPosition() == 3) {
return;
} else if(cursorPosition() == 7) {
pos = 3;
} else if(cursorPosition() == 11) {
pos = 7;
} else if(cursorPosition() == 15) {
pos = 11;
}
showIp();
break;
case Qt::Key_Backspace:
qDebug() << "backspace:" << cursorPosition() << endl;
if (cursorPosition() == 3) {
if (ip1.isEmpty()) {
} else {
ip1.remove(ip1.length() - 1, 1);
}
}
if (cursorPosition() == 7) {
if (ip2.isEmpty()) {
pos = 3;
} else {
ip2.remove(ip2.length() - 1, 1);
}
}
if (cursorPosition() == 11) {
if (ip3.isEmpty()) {
pos = 7;
} else {
ip3.remove(ip3.length() - 1, 1);
}
}
if (cursorPosition() == 15) {
if (ip4.isEmpty()) {
pos = 11;
} else {
ip4.remove(ip4.length() - 1, 1);
}
}
showIp();
default:
event->accept();
break;
}
}
}
void IpInput::showIp()
{
QString str = QString("%1.%2.%3.%4").
arg(ip1, 3, QLatin1Char(' ')).
arg(ip2, 3, QLatin1Char(' ')).
arg(ip3, 3, QLatin1Char(' ')).
arg(ip4, 3, QLatin1Char(' '));
setText(str);
setCursorPosition(pos);
}
QSize IpInput::sizeHint() const
{
QFontMetrics fm(font());
qDebug() << "sizeHint" << endl;
return QSize(fm.width("WWW.WWW.WWW.WWW")+10, fm.height());
}