首页 > 编程语言 >Qt实现Android的图案密码(图形解锁)源码分享

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

时间:2024-12-25 16:59:22浏览次数:10  
标签:Qt int radiu 源码 PatternCodeLockState patternCodeLockSetUpState Android event pai

一、效果展示

在这里插入图片描述

在这里插入图片描述

二、源码分享

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!

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

标签:Qt,int,radiu,源码,PatternCodeLockState,patternCodeLockSetUpState,Android,event,pai
From: https://blog.csdn.net/qq_15181569/article/details/144721279

相关文章

  • 基于Cecil源码的IL练级攻略(2)Metadata存储结构
    目录简介什么是元数据MetadataHeader参考文献简介上文提到CLRRuntimeHeader中包含metadatadirectory,我们可以通过这个字段访问对应的元数据信息。本篇文章会大致介绍一下元数据metadata以及它的存储结构。后续的文章都将基于本篇文章,因此如果有不理解的地方,推荐重新再看一......
  • Springboot旧衣捐赠平台设计与实现p40x5(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表用户,公益活动,捐赠信息,物品分类,地区分类,捐赠数据,捐赠接收开题报告内容一、研究背景与意义研究背景随着经济的快速发展和消费意识的提高,旧衣物的废弃量不......
  • Springboot旧商品销售系统4104m(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表用户,卖家,商品分类,商品信息开题报告内容一、项目背景与意义随着经济的快速发展和人们消费观念的转变,旧商品市场逐渐兴起。许多消费者开始注重资源的循环利用,......
  • Springboot旧教材交易系统a6151(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表用户,书籍类型,书籍信息开题报告内容一、研究背景随着高等教育的普及和校园生活的丰富多彩,学生们在学习和生活中积累了大量的旧教材。这些旧教材对于个人而言,可......
  • 零基础入门Spring源码
    文章目录前言Spring相关代码pom.xml配置文件beans.xml实体类测试类一、创建BeanFactoryApplicationContextBeanFactory和ApplicationContext的区别补充如何从容器中获取对象?二、读取xml等,将bean定义信息放入BeanDefinition三、对BeanDefinition中的属性值进行替换补充......
  • RTSP播放器EasyPlayer.js遇到Android播放器修复播放画面卡在第一帧问题
    在数字化时代,流媒体技术已经成为信息传播和娱乐消费的重要方式。随着互联网技术的飞速发展和移动设备的普及,流媒体服务正在重塑我们的生活和工作方式。从视频点播、在线直播到音乐流媒体,流媒体技术的广泛应用不仅改变了内容的分发和消费模式,也为内容创作者和消费者提供了前所未有......
  • 源码编译geoserver(idea)
    官方教程:https://docs.geoserver.org/main/en/developer/quickstart/intellij.html 从git存储库中检出源代码:gitclonehttps://github.com/geoserver/geoserver.gitgeoserver列出可用的分支:%gitbranch2.21.x2.22.x*main选择main最新动态:%gi......
  • qt读写ini文件
    [group1]key1=val1key2=val2sameKay=sameVal[group2]jian1=zhi1jian2=zhi2sameKay=sameZhi 比如创建插入一组ini文件,下面是文件写入的代码;Ini文件的写入ini文件不需要像xml和json一样需要使用QFile打开文件,只需将文件路径及文件格式传入即可(下方代码运行完毕,ini文件则会更新......
  • 计算机毕业设计 | SpringBoot+vue高校专业实习管理系统 大学生实训管理(附源码+论文)
    1,绪论1.1项目背景随着高等教育的快速发展,专业实习已成为培养学生实践能力、创新能力和职业素养的重要环节。然而,传统的人工管理方式存在效率低、易出错、信息不透明等问题,难以满足当前高校对专业实习管理的需求。因此,开发一套高效、便捷、智能化的高校专业实习管理系统显......
  • 计算机毕业设计 | SpringBoot+vue库存管理系统 企业采购进存销仓库管理(附源码+论文)
    1,绪论1.1选题动因在现在社会,对于信息处理方面,是有很高的要求的,因为信息的产生是无时无刻的,并且信息产生的数量是呈几何形式的增加,而增加的信息如何存储以及短时间分析检索,也是有时效性的,所以,不管是任何的企业和个人,只要需要处理信息,必然是要寻找到一个适合自己的解决方案......