Qt 实现滑块验证

最近想着模仿QQ第一次在电脑登录时候的滑块验证
效果如下
在这里插入图片描述
主代码:
PuzzleWidget.h

#ifndef PUZZLEWIDGET_H
#define PUZZLEWIDGET_H
#include <QWidget>
class PuzzleWidget : public QWidget
{
	Q_OBJECT
	Q_PROPERTY(QString pixmap READ getPixmap WRITE setPixmap)
public:
	PuzzleWidget(QWidget *parent);
	~PuzzleWidget();
public:
    QString getPixmap() const { return m_pixmap; }; //获得图片
    void setPixmap(const QString& pixmap);    //设置组图
	void setValue(int value);
    bool isOverlap();   //是否重合

private slots:
	void onUpdatePixmap();  //更新位图

protected:
	void paintEvent(QPaintEvent *event);

private:
	int m_value;
	QString m_pixmap;
	QPoint m_offsetPoint;
};

#endif // PUZZLEWIDGET_H

PuzzleWidget.cpp

#include "puzzlewidget.h"

#include <QPainter>
#include <QPainterPath>
#include <QTime>
#include <QTimer>

const int squarewidth = 46;
const int squareradius = 20;
PuzzleWidget::PuzzleWidget(QWidget *parent)
	: QWidget(parent)
{
	m_value = 0;
	m_offsetPoint = QPoint(0, 0);
	qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
}

PuzzleWidget::~PuzzleWidget()
{

}

void PuzzleWidget::setPixmap(const QString& pixmap)
{
	m_pixmap = pixmap;
	QTimer::singleShot(10, this, SLOT(onUpdatePixmap()));
}

void PuzzleWidget::onUpdatePixmap()
{
	m_offsetPoint.rx() = qBound(0, qrand() % this->width() + squarewidth + squareradius, this->width() - squarewidth - squareradius);
	m_offsetPoint.ry() = qBound(0, qrand() % this->height() + squarewidth + squareradius, this->height() - squarewidth - squareradius);
	update();
}

void PuzzleWidget::setValue(int value)
{
	m_value = qBound(0, value, this->width() - squarewidth - squareradius + m_offsetPoint.x());
	update();
}

void PuzzleWidget::paintEvent(QPaintEvent *event)
{
	QPainter painter(this);
	painter.setRenderHints(QPainter::Antialiasing);
	QPainterPath clippath;
	clippath.addRoundedRect(this->rect(), 4, 4);
	painter.setClipPath(clippath);
	const QPixmap& pixmap = QPixmap(m_pixmap).scaled(this->width(), this->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
	painter.drawPixmap(0, 0, this->width(), this->height(), pixmap);

	QPainterPath cutoutpath;
	cutoutpath.setFillRule(Qt::WindingFill);
	QRect rect(m_offsetPoint, QSize(squarewidth, squarewidth));
	cutoutpath.addRoundedRect(rect, 2, 2);
	cutoutpath.addEllipse(rect.center().x() - squareradius / 2, rect.top() - squareradius + 6, squareradius, squareradius);
	QPainterPath subellipseparh;
	subellipseparh.addEllipse(rect.right() - squareradius + 6, rect.center().y() - squareradius / 2, squareradius, squareradius);
	cutoutpath -= subellipseparh;

	painter.setPen(QPen(QColor(80, 80, 80), 1));
	painter.setBrush(QColor(100, 100, 100, 220));
	painter.drawPath(cutoutpath);

	QPixmap puzzlePixmap(this->size());
	puzzlePixmap.fill(Qt::transparent);
	QPainter puzzlePainter(&puzzlePixmap);
	puzzlePainter.setRenderHints(QPainter::Antialiasing);
	puzzlePainter.setClipPath(cutoutpath);
	puzzlePainter.setPen(QPen(QColor(80, 80, 80), 2));
	puzzlePainter.setBrush(QColor(200, 200, 200, 100));
	puzzlePainter.drawPixmap(0, 0, this->width(), this->height(), pixmap);
	puzzlePainter.drawPath(cutoutpath);

	painter.drawPixmap(-m_offsetPoint.x() + m_value, 0, this->width(), this->height(), puzzlePixmap);
}

bool PuzzleWidget::isOverlap()
{
	return qAbs(-m_offsetPoint.x() + m_value) < 5;
}

SliderPuzzleWidget.h

#ifndef SLIDERPUZZLEWIDGET_H
#define SLIDERPUZZLEWIDGET_H

#include <QWidget>
#include "ui_sliderpuzzlewidget.h"

//滑块验证
class SliderPuzzleWidget : public QWidget
{

	Q_OBJECT

public:
	SliderPuzzleWidget(QWidget *parent = 0);
	~SliderPuzzleWidget();

private:
	void initForm();

private slots:
    void onUpdateWidget();   //更新widget
    void onSliderValueChanged(int value);    //滑条数值改变
    void onSliderReleased();    //滑条释放

private:
	Ui::SliderPuzzleWidget ui;
};

#endif // SLIDERPUZZLEWIDGET_H

SliderPuzzleWidget .cpp

#pragma execution_character_set("utf-8")
#include "sliderpuzzlewidget.h"

#include <QTimer>
#include <QMessageBox>
#include <QDebug>
#include <QTime>

SliderPuzzleWidget::SliderPuzzleWidget(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);
    this->initForm();
    this->setFixedHeight(400);
    this->setFixedWidth(600);
}

SliderPuzzleWidget::~SliderPuzzleWidget()
{

}

//初始化界面
void SliderPuzzleWidget::initForm()
{
	QTimer::singleShot(10, this, SLOT(onUpdateWidget()));
	connect(ui.horizontalSlider, &QSlider::valueChanged, this, &SliderPuzzleWidget::onSliderValueChanged);
	connect(ui.horizontalSlider, &QSlider::sliderReleased, this, &SliderPuzzleWidget::onSliderReleased);
    ui.puzzlewidget->setPixmap(":/FrmSlidePuzzleWidget/Resources/ZW1.jpg");//默认图片
}

//设置坏块范围
void SliderPuzzleWidget::onUpdateWidget()
{
	ui.horizontalSlider->setRange(0, this->width());
}

//滑块值改变
void SliderPuzzleWidget::onSliderValueChanged(int value)
{
	ui.puzzlewidget->setValue(value);
}

//滑块释放
void SliderPuzzleWidget::onSliderReleased()
{
    //判断是否重合
	QString content = ui.puzzlewidget->isOverlap() ? "验证成功!" : "验证失败!";
	QMessageBox msgBox;
	msgBox.setWindowTitle("滑块图片验证码");
	msgBox.setText(content);
	msgBox.exec();

	//轮流切换图片
	static int testIndex = 1;
	testIndex = testIndex + 1 > 4 ? 1 : testIndex + 1;
	ui.horizontalSlider->setValue(0);
    ui.puzzlewidget->setPixmap(QString(":/FrmSlidePuzzleWidget/Resources/ZW%1.jpg").arg(testIndex));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值