C++ QT实现验证码功能

codearea.h
cpp 复制代码
#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
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();
}

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

相关推荐
Ajiang28247353041 小时前
对于C++中stack和queue的认识以及priority_queue的模拟实现
开发语言·c++
幽兰的天空1 小时前
Python 中的模式匹配:深入了解 match 语句
开发语言·python
Theodore_10224 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
‘’林花谢了春红‘’6 小时前
C++ list (链表)容器
c++·链表·list
----云烟----6 小时前
QT中QString类的各种使用
开发语言·qt
lsx2024066 小时前
SQL SELECT 语句:基础与进阶应用
开发语言
开心工作室_kaic7 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
向宇it7 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
武子康7 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
转世成为计算机大神7 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式