本文主要介绍了Qt实现自定义验证码控件的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值。
验证码的原理基于人类视觉和计算机视觉的差异性。通过给用户显示一些难以被机器识别的图形或文字,让用户进行人机交互,确认自己的身份。这样可以防止机器大规模注册、机器暴力破解数据密码等危害。
一、简述
使用Qt实现字符验证码自定义控件。 主要的编程思想还是实现自定义控件的封装性和共用性。
二、效果
三、实现步骤
1、验证码自定义控件
verificationwidget.h
#ifndef VERIFICATIONWIDGET_H
#define VERIFICATIONWIDGET_H
#include <QWidget>
#include <QPainter>
#include <QMouseEvent>
class VerificationWidget : public QWidget
{
Q_OBJECT
public:
explicit VerificationWidget(QWidget *parent = nullptr);
~VerificationWidget();
void generate(int count=4);//生成验证码,默认4位
bool check(QString text);//检验输入的验证码是否正确
protected:
virtual void paintEvent(QPaintEvent *event);//重写绘图事件
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseReleaseEvent (QMouseEvent *event);
signals:
void clicked();
private slots:
void changeCode();
private:
void initChars();//初始化字符集
void initColors();//初始化颜色集
void initDefaultFont();//初始化字体
void drawDisturb(QPainter &painter);//绘制干扰元素
void rotateAngle(QPainter &painter);//旋转角度
void scaleSize(QPainter &painter);//放缩大小
void shearForm(QPainter &painter);//扭曲形态
void draw(QPainter &painter);//绘制验证码
private:
int m_iPressed;
int boxHeight;//部件的宽高,由字体确定
int boxWidth;
QString m_strCode;//验证码的字符集
QStringList m_randChar;//随机产生的字符集
QVector<QColor> m_vecColor;//验证码的颜色集
};
#endif // VERIFICATIONWIDGET_H
verificationwidget.cpp
#include "verificationwidget.h"
VerificationWidget::VerificationWidget(QWidget *parent) : QWidget(parent)
{
qsrand(time(0));
initChars();
initColors();
initDefaultFont();
generate();
m_iPressed = 0;
connect(this, &VerificationWidget::clicked, this, &VerificationWidget::changeCode);
}
VerificationWidget::~VerificationWidget()
{
}
void VerificationWidget::initChars()
{
//初始化英文字符(数字和大小写字母)
m_strCode = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
}
void VerificationWidget::initColors()
{
m_vecColor<<QColor(Qt::black)<<QColor(Qt::red)<<QColor(Qt::darkRed)<<QColor(Qt::darkGreen)
<<QColor(Qt::blue)<<QColor(Qt::darkBlue)<<QColor(Qt::darkCyan)<<QColor(Qt::magenta);
}
void VerificationWidget::initDefaultFont()
{
QFont font;
font.setFamily("微软雅黑");
font.setBold(true);
font.setPointSizeF(20);
setFont(font);
}
void VerificationWidget::generate(int count)
{
m_randChar.clear();
int num = m_strCode.size();
for(int i=0;i<count;i++)
{
m_randChar.push_back(m_strCode.mid(qrand()%num,1));
}
boxHeight = this->fontMetrics().height()+12;
boxWidth = this->fontMetrics().width("W")*count+12;
setFixedSize(boxWidth,boxHeight);
}
void VerificationWidget::drawDisturb(QPainter &painter)
{
int num = m_vecColor.size();
if(qrand()%2)//干扰线
{
painter.setPen(QPen(QBrush(QColor(m_vecColor.at(qrand()%num))),1));
painter.drawLine(0,qrand()%boxHeight,boxWidth,qrand()%boxHeight);
painter.drawLine(0,qrand()%boxHeight,boxWidth,qrand()%boxHeight);
painter.drawLine(0,qrand()%boxHeight,boxWidth,qrand()%boxHeight);
painter.drawLine(0,qrand()%boxHeight,boxWidth,qrand()%boxHeight);
}
else
{
painter.setPen(QPen(QBrush(QColor(m_vecColor.at(qrand()%num))),1));
painter.drawLine(0,boxHeight/5,boxWidth,boxHeight/5);
painter.drawLine(0,boxHeight/5*2,boxWidth,boxHeight/5*2);
painter.drawLine(0,boxHeight/5*3,boxWidth,boxHeight/5*3);
painter.drawLine(0,boxHeight/5*4,boxWidth,boxHeight/5*4);
painter.drawLine(boxWidth/6,0,boxWidth/6,boxHeight);
painter.drawLine(boxWidth/6*2,0,boxWidth/6*2,boxHeight);
painter.drawLine(boxWidth/6*3,0,boxWidth/6*3,boxHeight);
painter.drawLine(boxWidth/6*4,0,boxWidth/6*4,boxHeight);
painter.drawLine(boxWidth/6*5,0,boxWidth/6*5,boxHeight);
}
for(int i=0;i<500;i++)//干扰点
{
painter.setPen(QPen(QBrush(QColor(m_vecColor.at(qrand()%num))),1));
painter.drawPoint(qrand()%boxWidth,qrand()%boxHeight);
}
}
void VerificationWidget::rotateAngle(QPainter &painter)
{
//旋转随机角度
if(qrand()%2)
{
painter.rotate(qrand()%20);
}
else
{
painter.rotate(-qrand()%20);
}
}
void VerificationWidget::scaleSize(QPainter &painter)
{
double xSize = (qrand()%3+9)/10.0;
double ySize = (qrand()%5+9)/10.0;
painter.scale(xSize,ySize);
}
//随机扭曲字符
void VerificationWidget::shearForm(QPainter &painter)
{
//扭曲的效果 范围-0.3-0.3
double xShear = qrand()%4/10.0;
double yShear = qrand()%4/10.0;
if(qrand()%2)
{
xShear = -xShear;
}
if(qrand()%2)
{
yShear = -yShear;
}
painter.shear(xShear,yShear);
}
void VerificationWidget::draw(QPainter &painter)
{
drawDisturb(painter);
int num = m_vecColor.size();
int charWidth = (boxWidth-12)/m_randChar.size();
for(int i=0;i<m_randChar.size();i++)
{
painter.setPen(QColor(m_vecColor.at(qrand()%num)));
painter.save();
int charSpace = (charWidth-this->fontMetrics().width(m_randChar.at(i)))/2;
charSpace += 12/6;
painter.translate(i*charWidth+charSpace,0);
if(qrand()%2)
{
rotateAngle(painter);
scaleSize(painter);
}
else
{
shearForm(painter);
}
painter.drawText(0,boxHeight-12,m_randChar.at(i));
painter.restore();
}
}
bool VerificationWidget::check(QString text)
{
QString verificationString = m_randChar.join("");
if(text.compare(verificationString,Qt::CaseInsensitive)==0)//不区分大小写
{
return true;
}
else
{
return false;
}
}
void VerificationWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setPen(Qt::NoPen);
painter.setBrush(QBrush(Qt::white));
QRect rect(QPoint(0,0),this->size());
painter.drawRect(rect);
draw(painter);
QWidget::paintEvent(event);
}
void VerificationWidget::mousePressEvent(QMouseEvent *event)
{
Q_UNUSED(event);
m_iPressed = 1;
}
void VerificationWidget::mouseReleaseEvent (QMouseEvent *event)
{
Q_UNUSED(event);
if(m_iPressed)
{
emit clicked();
m_iPressed = 0;
}
}
void VerificationWidget::changeCode()
{
generate();//生成新的验证码
update();
}
2、使用示例
创建UI界面:在QT Designer中创建一个UI界面,添加一个Label标签,一个Button按钮,一个lineEdit输入框以及一个widget控件,并将widget提升为VerificationWidget验证码自定义控件。
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->label->hide();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
ui->label->show();
if(ui->widget->check(ui->lineEdit->text()))
{
ui->label->setText(tr("验证码输入正确"));
}
else
{
ui->label->setText(tr("验证码输入错误"));
}
}
到此这篇关于Qt实现自定义验证码控件的方法的文章就介绍到这了。