先说下功能:
就是简单以的四位数字+字母组合的验证码,控件的宽度会被锁定最少为高度的两倍(如果宽度少于高度的两倍,高度会被强制缩小至宽度的二分之一)。
整个widget的区域会平分为4份来绘制字符(防止覆盖了),字符会以随机的大小(有最小限制)、随机的比例(拉伸比例有最小限制,高度不得低于宽度的三分之一,拉太扁就看不清了(╯‵□′)╯︵┻━┻)、随机的旋转角度(不会转出区域外且最大顺逆时针转45°)在对应区域的随机位置出现。
拉伸策略可以设置为preferred,不过直接拉伸的话是将当前的图直接放大,重新刷新才会根据当前长宽重新绘制。具体看图吧
写的有点复杂也有点乱,裁剪Image那个效率有点低,不得不降低图片大小以及跳行遍历来提升效率,欢迎指正或意见。
或许之后会另外一篇来讲下每个方法思路?(如果都看不懂的话(╯‵□′)╯︵┻━┻)
下面就贴下源码
头文件Vf_widget.h
#ifndef VF_WIDGET_
#define VF_WIDGET_
#include <QtWidgets>
#include <QtGlobal>
#include <QPainter>
#include <QEvent>
#include <QTime>
#include <QFont>
#include <QFontDatabase>
#include <QStringList>
#include <QImage>
#include <cmath>
#define Vf_PI 3.141592654
class Vf_widget : public QWidget
{
Q_OBJECT
signals:
void result(bool result);
signals:
void flash_code();
signals:
void getCaption(QChar* p_cap);
public:
typedef enum {
Just_accept, //仅接受鼠标点击事件但不作处理
Click_left, //左键单击刷新
Click_right, //右键
Double_left, //左键双击刷新
Double_right, //右键双击
Ignore_click //忽略鼠标点击事件,传递给父组件
}Flash_mode;
typedef enum {
Allow,
Prohibit
}Opinion;
struct For_var{
For_var() {};
~For_var() {
if (img_char != NULL) delete img_char;
if (fm_text != NULL) delete fm_text;
};
QPainter painter_font; //绘制单个字符到QImge的画笔
QPoint p_topleft; //当前绘制字符的初始位置的左上角坐标
QRect r_font; //当前字符的rect,控制字符大小及拉伸情况等
qreal diagonal; //当前rect的对角线长度,单位是pixel
qreal max_angle; //当前rect的最大可旋转弧度(顺时针)
qreal min_angle; //当前rect的最大可旋转弧度(逆时针)
qreal d_angle; //对角线diagnoal与当前rect的高(r_font.height)的夹角弧度
int l_size; //p_topleft距离左边缘的长度
int r_size; //p_topleft距离右边缘的长度
int font_angle; //当前绘制字符的旋转角度(非弧度)
QFont f_text; //文本字体
QFontMetrics *fm_text; //获取font的大小等参数
QImage *img_char; //绘制当前字符
};//绘制验证码的循环体内需要用到的变量
Vf_widget(int width = 360, int height = 90, Flash_mode mode = Just_accept, QWidget *parent = Q_NULLPTR);
~Vf_widget();
void setFlash_mode(Flash_mode mode);
void reflash();
bool check(QString caption);
protected:
void paintEvent(QPaintEvent *e);
void mousePressEvent(QMouseEvent *e);
void mouseDoubleClickEvent(QMouseEvent *e);
void resizeEvent(QResizeEvent *e);
private:
int width;
int height;
typename Vf_widget::Flash_mode mode;
typename Vf_widget::Opinion flash_opinion;
Qt::GlobalColor color[4];
QChar caption[5];
QStringList *fon