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

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

相关推荐
橘猫云计算机设计14 分钟前
基于JavaWeb的二手图书交易系统(源码+lw+部署文档+讲解),源码可白嫖!
java·开发语言·前端·毕业设计·php
半桔15 分钟前
红黑树剖析
c语言·开发语言·数据结构·c++·后端·算法
江烽渔火23 分钟前
C++ 多态
开发语言·c++
今天_也很困31 分钟前
牛客2025年愚人节比赛
c++·算法
嘤国大力士32 分钟前
C++11&QT复习 (十)
java·c++·qt
only-lucky33 分钟前
QT之QML(简单示例)
前端·javascript·qt
Joe_Wang534 分钟前
[图论]拓扑排序
数据结构·c++·算法·leetcode·图论·拓扑排序
m0_4902406740 分钟前
软件自动化测试(1):python+selenium自动化测试环境搭建
开发语言·python·selenium
2401_858286111 小时前
CD21.【C++ Dev】类和对象(12) 流插入运算符的重载
开发语言·c++·算法·类和对象·运算符重载
上理考研周导师1 小时前
【虚拟仪器技术】Labview虚拟仪器技术应用教程习题参考答案[13页]
服务器·开发语言