#ifndef QWHGESTURELOGIN_H
#define QWHGESTURELOGIN_H
#include
#include
#include
#include
class QWHGestureLogin : public QWidget
{
Q_OBJECT
public:
struct PosInCircle
{
int i; //行
int j; //列
bool isIn; //是否在范围内
};
explicit QWHGestureLogin(QWidget *parent = nullptr);
~QWHGestureLogin();
void setPassword(const QString password);
QString getPassword();
bool checkPassword();
protected:
void paintEvent(QPaintEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void drawBg(QPainter *painter);
void drawOutCircle(QPainter *painter);
void drawTipLine(QPainter *painter);
void drawInCircle(QPainter *painter);
void drawJoinLine(QPainter *painter);
private:
double distance(int x1, int y1, int x2, int y2);
int posToNumber(int i, int j);
signals:
void correctPassword(bool isCorrect, QString password);
public slots:
private:
QColor m_bgColor; //背景色
QColor m_outCircleColor; //外圆颜色
QColor m_tipLineColor; //提示线颜色
QColor m_circleRingColor; //圆环颜色
int m_margin; //外边距
int m_radius; //圆相对半径
PosInCircle m_posInCircle; //判断点是否在圆内
bool m_pressed; //鼠标按下
bool m_showText; //是否显示文字
QVector m_vecInputPoints; //鼠标移动选点
QPoint m_followPoint; //鼠标跟随点
QString m_password; //原密码
QString m_inputPassword; //鼠标移动选点转换为密码
};
#endif // QWHGESTURELOGIN_H
核心代码
void QWHGestureLogin::paintEvent(QPaintEvent *event)
{
int width = this->width();
int height = this->height();
int side = qMin(width, height);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(width / 2, height / 2);
painter.scale(side / 200, side / 200);
drawBg(&painter);
drawOutCircle(&painter);
drawTipLine(&painter);
drawInCircle(&painter);
drawJoinLine(&painter);
}
void QWHGestureLogin::drawBg(QPainter *painter)
{
painter->save();
int width = this->width();
int height = this->height();
painter->setPen(Qt::NoPen);
painter->setBrush(m_bgColor);
painter->drawRect(-width / 2, -height / 2, width, height);
painter->restore();
}
void QWHGestureLogin::drawOutCircle(QPainter *painter)
{
painter->save();
QPen pen(m_outCircleColor, 2);
painter->setPen(pen);
painter->setBrush(Qt::NoBrush);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
int x = -5 * m_radius + j * 4 * m_radius;
int y = -5 * m_radius + i * 4 * m_radius;
painter->drawEllipse(x, y, m_radius * 2, m_radius * 2);
if (m_showText)
{
int number = posToNumber(i, j);
QString text = QString::number(number);
x = -4 * m_radius + j * 4 * m_radius;
y = -4 * m_radius + i * 4 * m_radius;
int textWidth = fontMetrics().width(text);
int textHeight = fontMetrics().height();
painter->drawText(x - textWidth / 2, y + textWidth / 2, text);
}
}
}
painter->restore();
}
void QWHGestureLogin::drawTipLine(QPainter *painter)
{
painter->save();
int offset = 3;
if (m_posInCircle.isIn)
{
if (!m_pressed)
{
painter->setPen(m_tipLineColor);
painter->setBrush(Qt::NoBrush);
int x = -m_radius * 5 + m_posInCircle.j * 4 * m_radius - offset;
int y = -m_radius * 5 + m_posInCircle.i * 4 * m_radius - offset;
int w = (m_radius + offset) * 2;
int h = (m_radius + offset) * 2;
QRect rect(x, y, w, h);
painter->drawEllipse(rect);
}
}
painter->restore();
}
void QWHGestureLogin::drawInCircle(QPainter *painter)
{
painter->save();
if (m_pressed)
{
int offset1 = 1;//圆环偏移量
int offset2 = 3;//内圆偏移量
if (m_posInCircle.isIn)
{
//绘制圆环
painter->setPen(m_circleRingColor);
painter->setBrush(m_circleRingColor);
int x = -m_radius * 5 + m_posInCircle.j * 4 * m_radius + offset1;
int y = -m_radius * 5 + m_posInCircle.i * 4 * m_radius + offset1;
int w = (m_radius - offset1) * 2;
int h = (m_radius - offset1) * 2;
QRect rect(x, y, w, h);
painter->drawEllipse(rect);
painter->setPen(m_outCircleColor);
painter->setBrush(m_outCircleColor);
x = -m_radius * 5 + m_posInCircle.j * 4 * m_radius + offset2;
y = -m_radius * 5 + m_posInCircle.i * 4 * m_radius + offset2;
w = (m_radius - offset2) * 2;
h = (m_radius - offset2) * 2;
rect = QRect(x, y, w, h);
painter->drawEllipse(rect);
x = -m_radius * 4 + m_posInCircle.j * 4 * m_radius;
y = -m_radius * 4 + m_posInCircle.i * 4 * m_radius;
if (!m_vecInputPoints.contains(QPoint(x, y)))
{
m_vecInputPoints.push_back(QPoint(x, y));
int number = posToNumber(m_posInCircle.i, m_posInCircle.j);
m_inputPassword += QString::number(number);
}
}
}
painter->restore();
}
void QWHGestureLogin::drawJoinLine(QPainter *painter)
{
painter->save();
QPen pen(m_outCircleColor, 3);
painter->setPen(pen);
//绘制连接线段
for (int i = 0; i < m_vecInputPoints.count() - 1; i++)
{
painter->drawLine(m_vecInputPoints[i], m_vecInputPoints[i + 1]);
}
int offset1 = 1;//圆环偏移量
int offset2 = 3;//内圆偏移量
//绘制连接圆
for (int i = 0; i < m_vecInputPoints.count(); i++)
{
int x = m_vecInputPoints[i].x() - m_radius + offset1;
int y = m_vecInputPoints[i].y() - m_radius + offset1;
int w = 2 * (m_radius - offset1);
int h = 2 * (m_radius - offset1);
painter->setPen(m_circleRingColor);
painter->setBrush(m_circleRingColor);
painter->drawEllipse(x, y, w, h);
x = m_vecInputPoints[i].x() - m_radius + offset2;
y = m_vecInputPoints[i].y() - m_radius + offset2;
w = 2 * (m_radius - offset2);
h = 2 * (m_radius - offset2);
painter->setPen(m_outCircleColor);
painter->setBrush(m_outCircleColor);
painter->drawEllipse(x, y, w, h);
}
//绘制跟随线
if (m_pressed && m_vecInputPoints.count() < 9)
{
int width = this->width();
int height = this->height();
int side = qMin(width, height);
int scale = side / 200;
int x = (m_followPoint.x() - width / 2) / scale;
int y = (m_followPoint.y() - height / 2) / scale;
if (m_vecInputPoints.count() > 0)
{
painter->setPen(pen);
painter->drawLine(m_vecInputPoints.last(), QPoint(x, y));
}
}
painter->restore();
}