首页 > 其他分享 >Qt实现字符验证码相关功能

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

时间:2024-07-10 12:26:11浏览次数:11  
标签:字符 boxHeight Qt boxWidth void 验证码 VerificationWidget painter

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

四、源代码下载

标签:字符,boxHeight,Qt,boxWidth,void,验证码,VerificationWidget,painter
From: https://blog.csdn.net/u012959478/article/details/140320262

相关文章

  • 如何在 Rust 中安全地处理 Openresty中的字符串?
    HelloWorldRust以简洁高效安全而闻名,那么我们怎么集成到C的项目中呢。尤其是字符串数据结构,该如何正确地交互。借此机会整理一下工作中遇到的难题,希望可以帮助大家走出坑。我们先回顾一下C中字符串的结构。在C语言中,字符是一个连续的内存地址空间以\0结尾。C语言的......
  • 代码随想录算法训练营第8天 | 复习字符串API、双指针
    2024年7月10日题344.翻转字符数组记得用双指针,时间复杂度最低。题541.反转字符串II首先自己实现一个String的reverse函数方便后面用,记得字符数组和字符串的互转方式。然后计算有多少组2k,分组处理即可。classSolution{publicStringreverseStr(Strings,intk){......
  • QT--SQLite
    配置类相关的表,所以我使用sqlite,且QT自带该组件;1.安装sqlite-tools-win-x64-3460000、SQLiteExpert5.4.31.575使用SQLiteExpert建好数据库.db文件,和对应的表后把db文件放在指定目录./db/program.db;2.选择sql组件3.新增数据库处理类,在使用数据库的地方调用类成员函数......
  • qt 用数据画一个图,并表示出来
    1.概要想用数据绘制一个画面,看有相机到播放的本质是啥。要点  //创建一个QImage对象,指定图像的宽度、高度和格式  QImageimage(width,height,QImage::Format_Grayscale8);  //将像素数据复制到QImage对象中  memcpy(image.bits(),pixelData,width......
  • Java字符串(String、字符串拼接、原理)
    文章目录一、String字符串1.1创建方式【直接赋值、new一个对象】1.1.1使用字符串字面值直接赋值:(1)字符串字面量创建String对象的转换过程(2)一些方法(3)说明1.1.2使用`new`关键字创建字符串对象,将内容赋值给变量:(1)`String`类有多个构造函数,其中一些常用的包括:(2)说明(3)引用的......
  • 关于Qt模型插入最后一行数据中存在未填满的项,点击导致崩溃的解决办法
    在使用Qt模型视图框架的时候,你可能会遇见这种情况:给QTableView设置设置模型的时候,网模型里面插入数据,因为数据是一行一行插入的,即要使用model的appandRow函数,但有时候最后一行数据没有填满一行,但是没有填满的那一部分仍然可以点击,如下代码:while(query.next()){ProductInf......
  • 字符串函数
    在编写程序的过程中,我们经常需要用到字符串函数,为了方便对字符串进行处理,C语言标准库中提供了一系列库函数。在使用标准库中的字符串函数之前,我们需要引用头文件string.h。接下来我们对经常用到的字符串函数进行逐一介绍。strlen的使用和模拟实现strlen的全称是stringlengt......
  • Qt:10.显示类控件(QLabel-显示文本或图像的控件、QLCDNumber -显示数字的特殊控件、QPr
    目录一、QLabel-显示文本或图像的控件:1.1QLabel介绍:1.2设置文本格式——textFormat属性:1.3设置图片——pixmap属性:1.4自动缩放——scaledContents属性:拓展:resizeEvent方法:1.5内容对齐方式——alignment属性:1.6自动换行——wordWrap属性:1.7 文本缩进——indent属性......
  • C#字符串操作:判断一个字符串是否存在于另一个字符串按特定字符分割后的子字符串中的几
    要判断一个字符串是否存在于另一个字符串按特定字符分割后的子字符串中,可以使用以下几种方法:方法一:使用Split和Array.Exists你可以使用Split方法将字符串分割成子字符串数组,然后使用Exists方法检查目标字符串是否在数组中:usingSystem;classProgram{staticvoid......
  • QT入门看这一篇就够(详解含qt源码)
     目录一、Qt概述1.1什么是Qt1.2Qt的发展史1.3Qt的优势1.4Qt版本1.5成功案例二、创建Qt项目2.1使用向导创建2.2一个最简单的Qt应用程序2.2.1main函数中2.2.2类头文件2.3.pro文件2.4命名规范 2.5QtCreator常用快捷键三、Qt按钮小程序3.1按钮的创建......