C++ QT实现验证码功能

news2024/11/15 4:22:36
codearea.h
#ifndef RENDERAREA_H
#define RENDERAREA_H

#include <QList>
#include <QPainterPath>
#include <QRect>
#include <QWidget>

#define DEF_CODECOUNT 4					// 验证码默认位数

#define DEF_NOISYPOINTCOUNT 60			// 噪点数量
#define DEF_CONVERSEROTATE 10			// 转换角度范围
#define DEF_CONVERSESCALE 15			// 转换大小范围

class CodeArea : public QWidget
{
    Q_OBJECT

public:
    CodeArea(QWidget *parent = 0);
	~CodeArea();

	/* 更换验证码图片 */
	void replaceCodePic();

	/* 设置验证码位数 */
	void setCodeCount(int nCodeCount);

	/* 设置噪点数量 */
	void setNoisyPointCount(int nNoisyPointCount);

	/* 检验验证码 */
	bool checkCode(QString sCode);

protected:
    void paintEvent(QPaintEvent *event);

private:
	/* 初始化验证码范围 */
	inline void initCodeRange();
	/* 初始化验证码可用颜色列表 */
	inline void initCodeColorList();
	/* 更新验证码 */
	inline void updateLoginCode();
	/* 更新验证码图片 */
	inline void updateCodePic();
	/* 更新用于与用户输入的验证码做比较的码 */
	inline void updateCode();
	/* 绘制边缘虚线框 */
    inline void drawOutline(QPainter &painter);
	/* 绘制验证码 */
	inline void drawCode(QPainter &painter, int nCodeIndex);
	/* 绘制噪点 */
	inline void drawNoisyPoint(QPainter &painter);
	/* 做验证码形态转换 */
	inline void drawConversion(QPainter &painter);
	/* 设置验证码图片 */
	inline void setCodePic(const QList<QPainterPath *> &lCodePic);

private:
	QString m_sCode = "";						// 用于与用户输入的验证码做比较的码 
	QStringList m_slCodeRange;					// 验证码生成范围
	QStringList m_slLoginCode;					// 验证码列表,用于生成验证码图片
	QPainterPath *m_pCodePic;					// 单个位的验证码图片
	QList<QPainterPath *> m_lCodePic;			// 验证码图片
	QList<Qt::GlobalColor> m_lCodeColor;		// 验证码可用颜色列表

	int m_nNoisyPointCount = DEF_NOISYPOINTCOUNT;
	int m_nConverseRotate = DEF_CONVERSEROTATE;
	int m_nConverseScale = DEF_CONVERSESCALE;
	int m_nCodeCount = DEF_CODECOUNT;
};

#endif // RENDERAREA_H
codearea.cpp
#include "codearea.h"

#include <QPainter>
#include <QPaintEvent>

CodeArea::CodeArea(QWidget *parent)
    : QWidget(parent)
{
	initCodeRange();
	initCodeColorList();
	replaceCodePic();
}

CodeArea::~CodeArea()
{
	if (m_pCodePic)
	{
		delete m_pCodePic;
		m_pCodePic = nullptr;
	}
}

/* 更换验证码图片 */
void CodeArea::replaceCodePic()
{
	updateLoginCode();
	updateCodePic();
}

/* 设置验证码位数 */
void CodeArea::setCodeCount(int nCodeCount)
{
	m_nCodeCount = nCodeCount;
}

/* 设置噪点数量 */
void CodeArea::setNoisyPointCount(int nNoisyPointCount)
{
	m_nNoisyPointCount = nNoisyPointCount;
}

/* 检验验证码 */
bool CodeArea::checkCode(QString sCode)
{
	updateCode();
	return m_sCode == sCode;
}

void CodeArea::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
	painter.fillRect(event->rect(), QBrush(Qt::white));

    painter.translate(0, 0);
    painter.save();
	painter.translate(event->rect().center().x() - m_lCodePic.size() / 2 * 6, event->rect().center().y());
	for (int i = 0; i < m_lCodePic.size(); i++)
	{
		drawConversion(painter);
		drawCode(painter, i);
		painter.translate(10, 0);
	}
    painter.restore();
    drawOutline(painter);
	drawNoisyPoint(painter);
}

/* 初始化验证码范围 */
void CodeArea::initCodeRange()
{
	m_slCodeRange = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
		"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
		"o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
		"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
		"O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
}

/* 初始化验证码可用颜色列表 */
void CodeArea::initCodeColorList()
{
	m_lCodeColor << Qt::darkRed << Qt::darkGreen << Qt::darkBlue << Qt::darkCyan 
		<< Qt::darkMagenta << Qt::darkYellow << Qt::darkGray;
}

/* 更新验证码 */
void CodeArea::updateLoginCode()
{
	m_slLoginCode.clear();
	for (int i = 0; i < m_nCodeCount; i++)
		m_slLoginCode << m_slCodeRange[qrand() % 62];
}

/* 更新验证码图片 */
void CodeArea::updateCodePic()
{
	m_lCodePic.clear();
	for (int i = 0; i < m_nCodeCount; i++)
	{
		m_pCodePic = new QPainterPath(QPointF(0, 0));
		QFont font;
		font.setBold(true);
		font.setPixelSize(20);
		QRect fontBoundingRect = QFontMetrics(font).boundingRect(m_slLoginCode[i]);
		m_pCodePic->addText(-QPointF(fontBoundingRect.center()), font, m_slLoginCode[i]);
		m_lCodePic << m_pCodePic;
	}

	setCodePic(m_lCodePic);
}

/* 更新用于与用户输入的验证码做比较的码 */
void CodeArea::updateCode()
{
	m_sCode = "";
	for (int i = 0; i < m_nCodeCount; i++)
	{
		m_sCode += m_slLoginCode[i];
	}
}

/* 绘制边缘虚线框 */
void CodeArea::drawOutline(QPainter &painter)
{
    painter.setPen(Qt::darkGreen);
    painter.setPen(Qt::DashLine);
    painter.setBrush(Qt::NoBrush);
    painter.drawRect(0, 0, 80, 20);
}

/* 绘制验证码 */
void CodeArea::drawCode(QPainter &painter, int nCodeIndex)
{
	painter.fillPath(*m_lCodePic[nCodeIndex], QBrush(m_lCodeColor[qrand() % 7]));
}

/* 绘制噪点 */
void CodeArea::drawNoisyPoint(QPainter &painter)
{
	painter.setPen(Qt::red);
	painter.setPen(Qt::DotLine);
	painter.setBrush(Qt::NoBrush);
	for (int i = 0; i < m_nNoisyPointCount; i++)
		painter.drawPoint(QPointF(qrand() % 80, qrand() % 20));
}

/* 做验证码形态转换 */
void CodeArea::drawConversion(QPainter &painter)
{
	if (qrand() % 2)
		painter.rotate(qrand() % m_nConverseRotate);
	else
		painter.rotate(-(qrand() % m_nConverseRotate));

	painter.scale((qrand() % m_nConverseScale + (100 - m_nConverseScale)) / 100.0 , 
		(qrand() % m_nConverseScale + (100 - m_nConverseScale)) / 100.0);
}

/* 设置验证码图片 */
void CodeArea::setCodePic(const QList<QPainterPath *> &lCodePic)
{
	this->m_lCodePic = lCodePic;
	update();
}


创作不易,小小的支持一下吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1910874.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

印尼“支付宝” DANA 如何借力 OceanBase 实现3个“关键零”

当前&#xff0c;移动支付在东南亚正迅猛发展&#xff0c;据谷歌、淡马锡与贝恩公司发布的报告预测&#xff0c;东盟地区蓬勃兴起的移动支付市场有望在2030年突破至2万亿美元的交易规模。 在此背景下&#xff0c;DANA作为印尼——东南亚最大经济体中的一员&#xff0c;秉持着推…

【docker 把系统盘空间耗没了!】windows11 更改 ubuntu 子系统存储位置

系统&#xff1a;win11 ubuntu 22 子系统&#xff0c;docker 出现问题&#xff1a;系统盘突然没空间了&#xff0c;一片红 经过排查&#xff0c;发现 AppData\Local\packages\CanonicalGroupLimited.Ubuntu22.04LTS_79rhkp1fndgsc\ 这个文件夹竟然有 90GB 下面提供解决办法 步…

磁力搜索引擎是什么?为什么有些资源喜欢用磁力链接?

磁力链接是什么东西&#xff1f;在日常生活中&#xff0c;我们接触的比较多的下载链接是直链。 所谓的直链简单来说就是直接指向服务器文件资源的链接&#xff0c;如B站app的下载链接&#xff0c;这种链接有统一的服务器提供保障&#xff0c;通常比较稳定&#xff0c;可以追溯源…

数据结构 —— Dijkstra算法

数据结构 —— Dijkstra算法 Dijkstra算法划分集合模拟过程打印路径 在上次的博客中&#xff0c;我们解决了使用最小的边让各个顶点连通&#xff08;最小生成树&#xff09; 这次我们要解决的问题是现在有一个图&#xff0c;我们要找到一条路&#xff0c;使得从一个顶点到另一个…

java之数组练习

思路&#xff1a; 代码&#xff1a; public static void main(String[] args) {char[] arrnew char[26];for (char i0;i<arr.length;i ){arr[i] (char) (Ai);}System.out.println(arr);} 结果&#xff1a;

VMware使用技巧

目录 1. 系统快照 1.1 拍摄快照 1.2 查看快照 1.3 应用/删除快照 2. 克隆虚拟机 3. 删除虚拟机 1. 系统快照 1.1 拍摄快照 将当前系统的状态保存下来&#xff0c;如果将来系统出现不可修复的故障&#xff0c;使用快照可以恢复操作系统&#xff1b; CentOS7——拍照—…

【STM32】MDK的编译过程及文件类型全解

1.编译过程简介 编译&#xff1a;MDK软件使用的编译器是armcc和armasm&#xff0c; 它们根据每个c/c和汇编源文件编译成对应的以“.o”为后缀名的对象文件(Object Code&#xff0c;也称目标文件)&#xff0c; 其内容主要是从源文件编译得到的机器码&#xff0c;包含了代码、数据…

Object方法重写

这篇文章大家随意看看就好&#xff0c;只是一点理解的东西&#xff0c;当然你也可以认真调查。 我们需要知道Obecj是java中的一个类&#xff0c;是所有类的父类&#xff0c;即超类。对&#xff0c;超级赛亚人的那个超。 我们需要关注其中的equals、tostring这两个方法。 例如&…

汇川Easy系列PLC使用本地脉冲5轴设置

根据官网手册可以看到&#xff0c;Easy302往上的系列都是支持本地5轴脉冲控制的 常规汇川PLC本地脉冲轴配置时&#xff0c;脉冲和方向的输出点都是成对出现的&#xff0c;但是easy如果要使用5轴的话&#xff0c;就需要自己定义方向 可以看到&#xff0c;Y0,Y1这两个点是单独…

接口测试课程结构

课程大纲 如图&#xff0c;接下来的阶段课程&#xff0c;依次专项讲解如下专题&#xff0c;能力级别为中级&#xff0c;进阶后基本为中高级&#xff1a; 1.接口基础知识&#xff1b; 2.抓包工具&#xff1b; 3.接口工具&#xff1b; 4.mock服务搭建&#xff08;数据模拟服务&am…

国产PLC能否使用无线通讯终端来实现无线通讯?让我们一探究竟

在工业生产车间内&#xff0c;PLC被广泛应用于自动化控制的各个环节。随着智能化工厂的建设&#xff0c;许多PLC仍处于信息孤岛状态&#xff0c;现要将厂区内分散的PLC都建立通讯&#xff0c;如果重新布线工厂量大且不美观&#xff0c;此时就需要用到工业PLC无线通讯设备来解决…

Presto报错:[Presto requires an Oracle or OpenJDK JVM (found Red Hat, Inc.)]

启动前: 已经搭建了jdk环境hadoop的jdk环境配置没有问题 启动Presto时&#xff0c;报错 解决方案: 可能是presto自身变量配置没生效在presto路径下找到bin目录, 进入启动脚本launcher 在 exec "$(dirname “ 0 " ) / l a u n c h e r . p y " " 0"…

守护舌尖安全,破解EHS管理难题,食品加工企业的可持续发展之路

在当今社会&#xff0c;食品安全与环境保护已成为全球关注的热点&#xff0c;食品加工企业作为连接农业与消费者的关键环节&#xff0c;其环境、健康与安全&#xff08;EHS&#xff09;管理水平直接关系到产品的质量和企业的可持续发展。然而&#xff0c;食品加工企业在EHS管理…

面壁智能发布端侧 AI 应用开发平台;快手推出肖像动画技术 LivePortrait丨 RTE 开发者日报

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「…

C# Winform自制多轴力臂(简单易懂,方便扩展)

WinForms框架广泛应用于上位机开发领域&#xff0c;其中对力臂的精准控制是常见需求之一。本文深入探讨了如何创建自定义的多轴力臂图形控件&#xff0c;不仅涵盖了力臂图形控件的角度调节机制&#xff0c;还详细展示了如何实现力臂运动的生动动态效果&#xff0c;为开发者提供…

AE-时间轴的基础操作

目录 预览&#xff08;快捷键空格&#xff09; 调整时间线显示比例&#xff08;Alt鼠标滚轮&#xff09; 控制预览长度&#xff08;B/N&#xff09; 逐帧移动&#xff08;笔记本&#xff1a;按住fn上下方向键&#xff09; 视频剪切&#xff08;ctrlshiftD&#xff09; 剪…

“El-Table二次封装“这样做【高级前端必备技能之一】

&#x1f525; 前言 这篇文章给大家分享一个高级自定义列表组件从0到1的开发过程&#xff0c;这个列表组件的主要功能有&#xff0c;列表拖拽排序&#xff0c;右侧操作按钮统一使用Tooltip展示&#xff0c;操作表头增加自定列表icon&#xff0c;点击icon可以对列表展示数据进行…

帮企建站包响应式建站源码系统 带完整的安装代码包以及搭建部署教程

系统概述 帮企建站包响应式建站源码系统是一款为企业和个人提供便捷、高效建站解决方案的工具。它融合了先进的技术和设计理念&#xff0c;旨在帮助用户轻松构建具有专业水准的网站&#xff0c;无论在桌面端还是移动端都能呈现出完美的展示效果。 该系统基于响应式设计原则&a…

怎么制作gif动图,视频制作GIF动画更简单

在社交媒体和网络交流中&#xff0c;GIF动画以其生动活泼的表现形式成为了表达情感、幽默和创意的热门媒介。无论是分享日常趣事&#xff0c;还是制作专业演示&#xff0c;一个恰到好处的GIF动图总能吸引目光&#xff0c;传递信息。 但你知道吗&#xff1f;即使没有专业的设计背…

有什么好的录屏软件?分享4款好评的软件!

在数字化时代&#xff0c;录屏软件已成为我们工作、学习和娱乐中不可或缺的工具。但面对市场上琳琅满目的录屏软件&#xff0c;我们该如何选择最适合自己的那一款呢&#xff1f;今天&#xff0c;就让我们一起来揭秘那些备受好评的录屏神器&#xff0c;帮助你轻松找到录屏的首选…