当前位置: 首页 > article >正文

Qt实现Android的图案密码(图形解锁)源码分享

一、效果展示

在这里插入图片描述

在这里插入图片描述

二、源码分享

PatternPasswordWidget .hpp

#ifndef PATTERNCODELOCKWIDGET_H
#define PATTERNCODELOCKWIDGET_H

#include <QWidget>
#include <QWidget>
#include <QTimer>

class PatternPasswordWidget : public QWidget
{
    Q_OBJECT
   public:
       PatternPasswordWidget(QWidget *parent = nullptr);
       ~PatternPasswordWidget()override;
       void reset();

       int getNumberOfEachRowAndCol() const;
       void setNumberOfEachRowAndCol(int newNumberOfEachRowAndCol);
   signals:
       void inputPasswordOverSignal(QString);

   protected:
       void paintEvent(QPaintEvent *event)override;
       void resizeEvent(QResizeEvent *event) override;
       void mouseMoveEvent(QMouseEvent *event)override;
       void mousePressEvent(QMouseEvent *event)override;
       void mouseReleaseEvent(QMouseEvent *event)override;
       void mouseDoubleClickEvent(QMouseEvent *event)override;

   private:
       void onHoverTimer();
       QString getPassWord();

       enum class CircularState
       {
           normal,//正常
           hoverOnInnerSamrtCircular//鼠标悬浮在中间的小圆上面
       };

       enum class PatternCodeLockState
       {
           notSet,
           setting,
           setted_valid,//有效
           setted_invalid//无效
       };

       int numberOfEachRowAndCol;
       PatternCodeLockState patternCodeLockSetUpState{PatternCodeLockState::notSet};
       QList<CircularState> circularStateList;
       QList<QRect> smartCircularRectList;
       bool isUpdateSmartCircularRect{true};
       QTimer hoverTimer;
       int radiu;
       int lastHoverIndex{-1};
       int currentchangeLength;
       bool mouseInSomeSmartCircular{false};
       QList<int> setList;
       QPoint settingMousPos;
};

#endif // PATTERNCODELOCKWIDGET_H

PatternPasswordWidget .cpp

#include "patternPasswordWidget.h"
#include <QPainter>
#include <QPainterPath>
#include <QPaintEvent>

PatternPasswordWidget::PatternPasswordWidget(QWidget *parent)
    : QWidget(parent)
{
    setMouseTracking(true);
    setMinimumSize(400,400);

    numberOfEachRowAndCol = 3;
    for (int i = 0;i < numberOfEachRowAndCol;++i)
    {
        for (int j = 0;j < numberOfEachRowAndCol;++j)
        {
            circularStateList << CircularState::normal;
            smartCircularRectList << QRect();
        }
    }

    connect(&hoverTimer,&QTimer::timeout,this,&PatternPasswordWidget::onHoverTimer);
    hoverTimer.setInterval(40);
}

PatternPasswordWidget::~PatternPasswordWidget()
{
}

void PatternPasswordWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing,true);
    const auto rect = event->rect();
    painter.fillRect(rect,QColor("#1D1D1D"));

    auto width = rect.width();
    auto height = rect.height();
    auto sideLength = std::min(width,height) - 20;
    auto halfSideLength = sideLength/2;

    QRect drawZoneRect = QRect(-halfSideLength,-halfSideLength,sideLength,sideLength);
    drawZoneRect.translate(rect.center());

    painter.save();
    painter.setPen(QPen(QBrush("#141414"),5));
    painter.drawRoundedRect(drawZoneRect,12,12);
    painter.restore();

    radiu = sideLength / (1 + 1 + numberOfEachRowAndCol * 2 + (numberOfEachRowAndCol - 1) * 3);

    bool mustUpdateCircularRect = isUpdateSmartCircularRect;
    for (int i = 0,listIndex = 0;i < numberOfEachRowAndCol;++i)
    {
        for (int j = 0;j < numberOfEachRowAndCol;++j,++listIndex)
        {
            QPoint circularCenter = drawZoneRect.topLeft() + QPoint(2*radiu + i*5*radiu,2*radiu + j*5*radiu);
            if(setList.contains(listIndex))
            {
                if(patternCodeLockSetUpState == PatternCodeLockState::setting ||
                   patternCodeLockSetUpState == PatternCodeLockState::setted_valid)
                {
                    painter.setPen(QPen(QBrush(QColor("#00FF80")),3));
                }
                else
                {
                    painter.setPen(QPen(QBrush(QColor("#FE4C40")),3));
                }
            }
            else
            {
                painter.setPen(QPen(QBrush(Qt::white),3));
            }

            if(listIndex == lastHoverIndex &&
               hoverTimer.isActive() &&
               patternCodeLockSetUpState == PatternCodeLockState::setting)
            {
                painter.drawEllipse(circularCenter,radiu + currentchangeLength,radiu + currentchangeLength);
            }
            else
            {
                painter.drawEllipse(circularCenter,radiu,radiu);
            }

            if(mustUpdateCircularRect)
            {
                QRect newCircularRect = QRect(-radiu/2,-radiu/2,radiu,radiu);
                newCircularRect.translate(circularCenter);
                smartCircularRectList[listIndex] = newCircularRect;
            }

            painter.save();
            switch (circularStateList.at(listIndex))
            {
                case CircularState::normal:
                {
                    if(listIndex == lastHoverIndex &&
                       hoverTimer.isActive() &&
                       patternCodeLockSetUpState == PatternCodeLockState::notSet)
                    {
                        painter.setBrush(Qt::white);
                        painter.setPen(Qt::transparent);
                        painter.drawEllipse(circularCenter,
                                            static_cast<int>(radiu * 0.5 + currentchangeLength),
                                            static_cast<int>(radiu * 0.5 + currentchangeLength));
                    }
                    else
                    {
                        painter.setBrush(QColor("#888888"));
                        painter.setPen(Qt::transparent);
                        painter.drawEllipse(circularCenter,radiu/2,radiu/2);
                    }
                }break;
                case CircularState::hoverOnInnerSamrtCircular:
                {
                    painter.setPen(Qt::transparent);

                    if(patternCodeLockSetUpState == PatternCodeLockState::notSet)
                    {
                        painter.setBrush(Qt::white);
                        if(hoverTimer.isActive())
                        {
                            painter.drawEllipse(circularCenter,
                                                static_cast<int>(radiu * 0.5 + currentchangeLength),
                                                static_cast<int>(radiu * 0.5 + currentchangeLength));
                        }
                        else
                        {
                            painter.drawEllipse(circularCenter,
                                                static_cast<int>(radiu * 0.7),
                                                static_cast<int>(radiu * 0.7));
                        }
                    }
                    else
                    {
                        if(patternCodeLockSetUpState == PatternCodeLockState::setting ||
                           patternCodeLockSetUpState == PatternCodeLockState::setted_valid)
                        {
                            painter.setBrush(QColor("#00FF80"));
                        }
                        else
                        {
                            painter.setBrush(QColor("#FE4C40"));
                        }
                        painter.drawEllipse(circularCenter,
                                            static_cast<int>(radiu * 0.7),
                                            static_cast<int>(radiu * 0.7));
                    }
                }break;
            }
            painter.restore();
        }
    }

    if(patternCodeLockSetUpState != PatternCodeLockState::notSet)
    {
        painter.setBrush(Qt::transparent);
        if(patternCodeLockSetUpState == PatternCodeLockState::setted_invalid)
        {
            painter.setPen(QPen(QBrush(QColor("#FE4C40")),7,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin));
        }
        else
        {
            painter.setPen(QPen(QBrush(QColor("#00FF80")),7,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin));
        }
        int setListSize = setList.size();
        for(int i = 0;i < setListSize;++i)
        {
            if(i < (setListSize - 1))
            {
                painter.drawLine(smartCircularRectList.at(setList.at(i)).center(),
                                 smartCircularRectList.at(setList.at(i + 1)).center());
            }
        }

        if(patternCodeLockSetUpState == PatternCodeLockState::setting)
        {
            painter.drawLine(smartCircularRectList.at(setList.last()).center(),
                             settingMousPos);
        }
    }

    if(mustUpdateCircularRect)
        isUpdateSmartCircularRect = false;
}

void PatternPasswordWidget::resizeEvent(QResizeEvent *event)
{
    isUpdateSmartCircularRect = true;
    QWidget::resizeEvent(event);
}

void PatternPasswordWidget::mouseMoveEvent(QMouseEvent *event)
{
    auto pos = event->pos();
    int currentHoverIndex = -1;
    if(patternCodeLockSetUpState == PatternCodeLockState::notSet)
    {
        bool mouseInSomeSmartCircular{false};
        for(int i = 0;i < smartCircularRectList.size();++i)
        {
            if(smartCircularRectList.at(i).contains(pos))
            {
                circularStateList[i] = CircularState::hoverOnInnerSamrtCircular;
                currentHoverIndex = i;
                mouseInSomeSmartCircular = true;
            }
            else
            {
                circularStateList[i] = CircularState::normal;
            }
        }

        if(mouseInSomeSmartCircular)
        {
            lastHoverIndex = currentHoverIndex;
            setCursor(Qt::PointingHandCursor);
        }
        else
        {
            setCursor(Qt::ArrowCursor);
        }

        if(!hoverTimer.isActive())
        {
            if(this->mouseInSomeSmartCircular != mouseInSomeSmartCircular)//鼠标进入了某个小圆或从小圆出来
            {
                this->mouseInSomeSmartCircular = mouseInSomeSmartCircular;
                if(this->mouseInSomeSmartCircular)
                {
                    currentchangeLength = 0;
                }
                else
                {
                    currentchangeLength = radiu * 0.2;
                }
                hoverTimer.start();
            }
        }
    }
    else if(patternCodeLockSetUpState == PatternCodeLockState::setting)
    {
        bool mouseInSomeSmartCircular{false};
        for(int i = 0;i < smartCircularRectList.size();++i)
        {
            if(smartCircularRectList.at(i).contains(pos))
            {
                if(!setList.contains(i))
                {
                    setList << i;
                    circularStateList[i] = CircularState::hoverOnInnerSamrtCircular;
                    currentHoverIndex = i;
                }
                mouseInSomeSmartCircular = true;
            }
        }

        if(this->mouseInSomeSmartCircular != mouseInSomeSmartCircular)
        {
            this->mouseInSomeSmartCircular = mouseInSomeSmartCircular;
            if(mouseInSomeSmartCircular)
            {
                lastHoverIndex = currentHoverIndex;
                setCursor(Qt::PointingHandCursor);

                if(!hoverTimer.isActive())
                {
                    currentchangeLength = 0;
                    hoverTimer.start();
                }
            }
            else
            {
                setCursor(Qt::ArrowCursor);
            }
        }

        settingMousPos = pos;
    }
    update();
    QWidget::mouseMoveEvent(event);
}

void PatternPasswordWidget::onHoverTimer()
{
    if(patternCodeLockSetUpState == PatternCodeLockState::notSet)
    {
        if(mouseInSomeSmartCircular)
        {
            if(currentchangeLength >= (radiu * 0.2))
            {
                hoverTimer.stop();
            }
            currentchangeLength += 2;
        }
        else
        {
            if(currentchangeLength <= -(radiu * 0.1))
            {
                hoverTimer.stop();
            }
            currentchangeLength -= 2;
        }
    }
    else if(patternCodeLockSetUpState == PatternCodeLockState::setting)
    {
        if(currentchangeLength >= (radiu * 0.1))
        {
            hoverTimer.stop();
        }
        currentchangeLength += 2;
    }
    update();
}

void PatternPasswordWidget::mousePressEvent(QMouseEvent *event)
{
    if(lastHoverIndex != -1)
    {
        if(patternCodeLockSetUpState == PatternCodeLockState::notSet)//开始设置
        {
            patternCodeLockSetUpState = PatternCodeLockState::setting;
            setList << lastHoverIndex;
            circularStateList[lastHoverIndex] = CircularState::hoverOnInnerSamrtCircular;
            settingMousPos = event->pos();
            currentchangeLength = 0;
            hoverTimer.start();
            update();
        }
    }

    QWidget::mousePressEvent(event);
}

void PatternPasswordWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if(patternCodeLockSetUpState == PatternCodeLockState::setting)
    {

        patternCodeLockSetUpState = PatternCodeLockState::setted_valid;
        emit inputPasswordOverSignal(getPassWord());

        update();
    }
    QWidget::mouseReleaseEvent(event);
}

void PatternPasswordWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
    if(patternCodeLockSetUpState == PatternCodeLockState::setting && !mouseInSomeSmartCircular)
    {

        patternCodeLockSetUpState = PatternCodeLockState::setted_valid;
        emit inputPasswordOverSignal(getPassWord());
        update();
    }

    QWidget::mouseDoubleClickEvent(event);
}

QString PatternPasswordWidget::getPassWord()
{
    QString psw;
    for(const int & value : setList)
    {
        psw.append(QString::number(value+1,16));
    }

    return psw;
}

int PatternPasswordWidget::getNumberOfEachRowAndCol() const
{
    return numberOfEachRowAndCol;
}

void PatternPasswordWidget::setNumberOfEachRowAndCol(int newNumberOfEachRowAndCol)
{
    if(newNumberOfEachRowAndCol > 1 && newNumberOfEachRowAndCol < 10)
    {
        reset();
        circularStateList.clear();
        smartCircularRectList.clear();
        numberOfEachRowAndCol = newNumberOfEachRowAndCol;
        for (int i = 0;i < numberOfEachRowAndCol;++i)
        {
            for (int j = 0;j < numberOfEachRowAndCol;++j)
            {
                circularStateList << CircularState::normal;
                smartCircularRectList << QRect();
            }
        }
        update();
    }
}

void PatternPasswordWidget::reset()
{
    patternCodeLockSetUpState = PatternCodeLockState::notSet;
    std::fill(circularStateList.begin(),circularStateList.end(),CircularState::normal);
    lastHoverIndex = -1;
    hoverTimer.stop();
    currentchangeLength = 0;
    isUpdateSmartCircularRect = true;
    mouseInSomeSmartCircular = false;
    setList.clear();
    settingMousPos = QPoint(0,0);
    update();
}

三、使用方法

新建一个Dialog界面
在这里插入图片描述
开始布局
在这里插入图片描述
在这里插入图片描述
将widgetPassword右键->提升为->然后选择PatternPasswordWidget类就OK!

觉得不错给作者点个赞呗!


http://www.kler.cn/a/452254.html

相关文章:

  • 「Python数据科学」标量、向量、矩阵、张量与多维数组的辨析
  • Windows下安装Rabbit MQ
  • Spring源码_05_IOC容器启动细节
  • 实现 QTreeWidget 中子节点勾选状态的递归更新功能只影响跟节点的状态父节点状态不受影响
  • 基于云计算的资源管理系统
  • 基于ceres优化的3d激光雷达开源算法
  • 计算机的错误计算(一百九十一)
  • 信息抽取(NLP)是什么技术有哪些应用?
  • 大数据-256 离线数仓 - Atlas 数据仓库元数据管理 正式安装 启动服务访问 Hive血缘关系导入
  • 《Web 搜索引擎优化》
  • CI/CD在前端项目的应用:实现自动化与持续交付
  • Go入门篇:(二)基础知识之结构,包,变量初探
  • my-sql编写技巧
  • 阿里云虚拟主机ecs镜像如何转移到本地virtualbox上
  • CH32V307VCT6---工程template创建
  • uniapp微信小程序,使用fastadmin完成一个一键获取微信手机号的功能
  • arcface
  • Linux configfs和sysfs的使用与理解
  • 开关电源中的高频振荡噪声及其抑制方法
  • 117.【C语言】数据结构之排序(选择排序)
  • 青蛇人工智能学家
  • 2025差旅平台怎么选?一体化、全流程降本案例解析
  • 用 Python 从零开始构建 LLaMA 3
  • 网络管理(Network Management,NM)(一)
  • 【唐叔学算法】第19天:交换排序-冒泡排序与快速排序的深度解析及Java实现
  • 斐波那契数【东北大学oj数据结构10-1】C++