QLineEdit 提供 4 种 EchoMode 状态。
输入密码时,QLineEdit::Password 很合适,因为它显示一个圆圈(或类似的东西)而不是输入的字符。
我想要做的是隐藏所有字符,就像 QLineEdit::Password 一样,但最后输入的字符在被圆圈替换之前会显示几秒钟。这允许用户检查他们是否正确使用了密码。
但是,在一段时间后我无法绘制圆圈符号而不是可见字符。
我尝试使用连接到 update() 插槽的 QTimer,但到目前为止没有成功。
lineeditvanishingcharacters.cpp
#include "lineeditvanishingcharacters.h"
#include <QTextLayout>
#include <QPainter>
LineEditVanishingCharacters::LineEditVanishingCharacters(QWidget *parent)
: QLineEdit(parent)
, m_is_new_character(false)
{
setEchoMode(QLineEdit::Password);
}
void LineEditVanishingCharacters::paintEvent(QPaintEvent *event)
{
if(text().isEmpty()) {
QLineEdit::paintEvent(event);
return;
}
// if not focused anymore
// then hide all characters
if(!hasFocus()) {
QLineEdit::paintEvent(event);
return;
}
// first paint as the default QLineEdit all characters but the last one
const QString first_characters = text().chopped(1);
const QString last_character = text().last(1);
setText(first_characters);
QLineEdit::paintEvent(event);
// restore the full text
setText(first_characters+last_character);
// ensure font() is up to date
ensurePolished();
// then, draw the last character
// &. compute the cursor position
const QRect cr = cursorRect();
const QPoint pos = cr.topRight() - QPoint(cr.width(), 0.);
// create the QTextLayout and add the last character to it
QTextLayout l(last_character, font());
l.beginLayout();
QTextLine line = l.createLine();
line.setLineWidth(width() - pos.x());
line.setPosition(pos);
l.endLayout();
QPainter p(this);
// set text color to match the textedit text color
p.setPen(palette().text().color());
l.draw(&p, QPoint(0, 0));
}
lineeditvanishingcharacters.h
#ifndef LINEEDITVANISHINGCHARACTERS_H
#define LINEEDITVANISHINGCHARACTERS_H
#include <QLineEdit>
#include <QPaintEvent>
class LineEditVanishingCharacters : public QLineEdit
{
Q_OBJECT
public:
LineEditVanishingCharacters(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent *event);
};
#endif // LINEEDITVANISHINGCHARACTERS_H
这是我的解决方案。最后一个字符在 500 毫秒后隐藏。
lineeditvanishingcharacters.cpp
#include "lineeditvanishingcharacters.h"
#include <QTextLayout>
#include <QPainter>
LineEditVanishingCharacters::LineEditVanishingCharacters(QWidget *parent)
: QLineEdit(parent)
, m_is_new_character(false)
{
setEchoMode(QLineEdit::Password);
connect(this, &LineEditVanishingCharacters::textEdited,
this, &LineEditVanishingCharacters::textHasBeenEdited);
m_timer = new QTimer(this);
connect(m_timer, &QTimer::timeout, this, [this]() {
update();
m_is_new_character = false;
});
m_timer->start(500); // 0.5 second
}
void LineEditVanishingCharacters::textHasBeenEdited()
{
m_is_new_character = true;
m_timer->start();
}
void LineEditVanishingCharacters::paintEvent(QPaintEvent *event)
{
// first paint as the default QLineEdit all characters but the last one
if(text().isEmpty()) {
QLineEdit::paintEvent(event);
return;
}
// no new character has been typed, then hide the full text
if(!m_is_new_character) {
QLineEdit::paintEvent(event);
return;
}
// if not focused anymore
// then hide all characters
if(!hasFocus()) {
QLineEdit::paintEvent(event);
return;
}
const QString first_characters = text().chopped(1);
const QString last_character = text().last(1);
setText(first_characters);
QLineEdit::paintEvent(event);
// restore the full text
setText(first_characters+last_character);
// ensure font() is up to date
ensurePolished();
// then, draw the last character
// &. compute the cursor position
const QRect cr = cursorRect();
const QPoint pos = cr.topRight() - QPoint(cr.width(), 0.);
// create the QTextLayout and add the last character to it
QTextLayout l(last_character, font());
l.beginLayout();
QTextLine line = l.createLine();
line.setLineWidth(width() - pos.x());
line.setPosition(pos);
l.endLayout();
QPainter p(this);
// set text color to match the textedit text color
p.setPen(palette().text().color());
l.draw(&p, QPoint(0, 0));
}
lineeditvanishingcharacters.h
#ifndef LINEEDITVANISHINGCHARACTERS_H
#define LINEEDITVANISHINGCHARACTERS_H
#include <QLineEdit>
#include <QPaintEvent>
class LineEditVanishingCharacters : public QLineEdit
{
Q_OBJECT
public:
LineEditVanishingCharacters(QWidget *parent = nullptr);
public Q_SLOTS:
void textHasBeenEdited();
protected:
void paintEvent(QPaintEvent *event);
private:
bool m_is_new_character;
};
#endif // LINEEDITVANISHINGCHARACTERS_H