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();
}

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

相关推荐
2501_9412366217 小时前
分布式日志系统实现
开发语言·c++·算法
星轨初途17 小时前
《数据结构二叉树之堆 —— 优先队列与排序的高效实现(2)(下)》
c语言·开发语言·数据结构·经验分享·笔记·性能优化
2501_9412355117 小时前
C++与机器学习框架
开发语言·c++·算法
2501_9411118617 小时前
C++模块化设计原则
开发语言·c++·算法
2501_9412375317 小时前
基于C++的游戏引擎开发
开发语言·c++·算法
_OP_CHEN17 小时前
算法基础篇:(十)贪心算法拓展之哈夫曼编码:从 “合并最优” 到数据压缩的传奇
c++·算法·贪心算法·蓝桥杯·哈夫曼编码·算法竞赛·acm/icpc
枫叶丹417 小时前
【Qt开发】Qt窗口(二) -> QToolBar工具栏
开发语言·数据库·c++·qt
熙客17 小时前
Java集合框架概述
java·开发语言
高山有多高18 小时前
堆应用一键通关: 堆排序 +TOPk问题的实战解析
c语言·数据结构·c++·算法
我命由我1234518 小时前
Java 开发 - 简单消息队列实现、主题消息队列实现
java·开发语言·后端·算法·java-ee·消息队列·intellij-idea