Bootstrap

Qt实现字符验证码相关功能

        本文主要介绍了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实现自定义验证码控件的方法的文章就介绍到这了。

四、源代码下载
;