Qt之QLineEdit实现密码定时密文显示

QLineEdit密码定时密文显示


文章目录

      • QLineEdit密码定时密文显示
      • 1、前言
      • 2、实现效果如下
      • 3、思路
      • 4、代码干货

1、前言

之前在项目中遇到密码输入框的需求。具体需求是在用户输入的时候,输入一个字符时明文显示,过两秒该字符密文显示。如果持续输入,所有字符,出最后一位之外全部密文显示,最后一位两秒之后,再密文显示。


2、实现效果如下

Qt之QLineEdit实现密码定时密文显示_第1张图片
过两秒之后
Qt之QLineEdit实现密码定时密文显示_第2张图片


3、思路

看到这个需求,明显和现在网页上或手机APP上显示的需求很类似。
但是QLineEidt本身具有4种内容显示方式。
enum EchoMode

Constant Value Description
QLineEdit::Normal 0 Display characters as they are entered. This is the default.
QLineEdit::NoEcho 1 Do not display anything. This may be appropriate for passwords where even the length of the password should be kept secret.
QLineEdit::Password 2 Display platform-dependent password mask characters instead of the characters actually entered.
QLineEdit::PasswordEchoOnEdit 3 Display characters as they are entered while editing otherwise display characters as with Password.

很可惜这四种方式肯定是无法满足需求的。
后来我又想探究 QLineEdit::Password 底层是怎么实现的,但是看了QLineEdit的源码时候并没有得到我想要的结果。
在我无处下手的时候,同事说直接用*代替就好了,当时就被我否定了,因为需求要的效果是●,*显然不行。不过这也为我提供了思路。是否可用其他特殊字符代替,后面通过度娘的帮助终于找到了。
UniCode 在 25CF(十进制9679)对应的特殊字符就是 ●
剩下的问题就很好解决了。


4、代码干货

以下代码仅供参考,可根据实际需求修改

class DSLineEdit : public QLineEdit
{
	Q_OBJECT

public:
	DSLineEdit(QWidget *parent = NULL);
	//explicit DSLineEdit(QWidget *parent = NULL);
	~DSLineEdit();

	void SetPassword(QString& strPwd);
	QString GetPassword();

	QString InputPassword(int iSize, QString strText);
	QString BackPassword(int iSize, QString strText);

protected:
	virtual void contextMenuEvent(QContextMenuEvent *pEvent);
	virtual bool eventFilter(QObject *obj, QEvent *pEvent);

public slots:
	void OnTimeOut();
	void OnTextChanged(const QString&);

private:
	QString				m_strPassword;
	QTimer*				m_tTimer;
};
DSLineEdit::DSLineEdit(QWidget *parent /*= NULL*/)
	: QLineEdit(parent)
	, m_strPassword("")
	, m_tTimer(NULL)
{
	setMaxLength(MAX_LENGTH);
	setValidator(new QIntValidator(this));

	m_tTimer = new QTimer(this);
	m_tTimer->setInterval(2000);
	connect(m_tTimer, SIGNAL(timeout()), this, SLOT(OnTimeOut()));
	connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(OnTextChanged(const QString&)));

	installEventFilter(this);
}

DSLineEdit::~DSLineEdit()
{
	if (m_tTimer != NULL)
	{
		if (m_tTimer->isActive())
		{
			m_tTimer->stop();
			delete m_tTimer;
		}
		m_tTimer = NULL;
	}
}

void DSLineEdit::SetPassword(QString& strPwd)
{
	m_strPassword = strPwd;
}

QString DSLineEdit::GetPassword()
{
	return m_strPassword;
}

QString DSLineEdit::InputPassword(int iSize, QString strText)
{
	ushort iSymbol = { 9679 };
	const QChar symbol = QChar(iSymbol);
	QString strTemp(iSize,symbol);

	const QChar temp = strText.at(strText.length() - 1);
	if (!temp.isNull())
	{
		strTemp.append(temp);
	}

	return strTemp;
}

QString DSLineEdit::BackPassword(int iSize, QString strText)
{
	ushort iSymbol = { 9679 };
	const QChar symbol = QChar(iSymbol);
	QString strTemp(iSize, symbol);

	return strTemp;
}

void DSLineEdit::contextMenuEvent(QContextMenuEvent *pEvent)
{
	QString temp = qGuiApp->clipboard()->text();
	qGuiApp->clipboard()->setText(QString());

	if (QMenu *menu = createStandardContextMenu())
	{
		menu->setAttribute(Qt::WA_DeleteOnClose);
		menu->popup(pEvent->globalPos());
	}

	qApp->clipboard()->setText(temp);
}

bool DSLineEdit::eventFilter(QObject *obj, QEvent *pEvent)
{
	if (pEvent->type() == QEvent::KeyPress)
	{
		QKeyEvent* keyEvent = static_cast(pEvent);
		if (keyEvent->matches(QKeySequence::Paste))
		{
			if (keyEvent->modifiers() == Qt::ControlModifier 
				&& keyEvent->key() == Qt::Key_V)
			{
				qDebug() << "========== Ctrl + v \n";
				return true;
			}
		}
	}

	if (pEvent->type() == QEvent::MouseButtonPress)
	{
		QMouseEvent* mouseEvent = static_cast(pEvent);
		if (mouseEvent->button() == Qt::MidButton)
		{
			qDebug() << "========== Mouse mid button release \n";
			return true;
		}
	}

	return QLineEdit::eventFilter(obj, pEvent);
}

void DSLineEdit::OnTimeOut()
{
	//setEchoMode(QLineEdit::Password);
	int iLength = m_strPassword.length();
	ushort iSymbol = { 9679 };
	const QChar symbol = QChar(iSymbol);
	QString strTemp(iLength, symbol);

	setText(strTemp);
}

void DSLineEdit::OnTextChanged(const QString& strText)
{
	QString strShowText = "";
	int iLength = m_strPassword.length();
	int iTempLength = strText.length();

	if (iLength < iTempLength)
	{
		strShowText = InputPassword(iLength, strText);

		if (m_tTimer != NULL)
		{
			m_tTimer->stop();
			m_tTimer->start();
		}
	}
	else if (iLength > iTempLength)
	{
		strShowText = BackPassword(iTempLength, strText);
	}
	else
	{
		return;
	}

	m_strPassword = strText;
	setText(strShowText);
}

以上代码大家可只做参考。

源码免费在此传送门

你可能感兴趣的:(Qt,学习之路,C++)