当前位置: 首页> 汽车> 车展 > QT滑块图片验证程序

QT滑块图片验证程序

时间:2025/7/9 11:06:22来源:https://blog.csdn.net/gdizcm/article/details/140242341 浏览次数: 0次

使用QT实现滑块验证程序,原理是画个图片,然后在图片上画个空白区域,再画个滑块图片。

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();
private:void initForm();void drawPicture();private slots:void onUpdateWidget();void onSliderValueChanged(int value);void onSliderReleased();void onUpdatePixmap();protected:bool eventFilter(QObject *watched, QEvent *event);void paintEvent(QPaintEvent *event);private:Ui::Widget *ui;QString m_pixmap;QPoint m_offsetPoint;int m_value;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QPaintEvent>
#include <QPainter>
#include <QPainterPath>
#include <QDebug>
#include <QMessageBox>
#include <QTimer>
#include <QSlider>
#include <QRandomGenerator>const int squarewidth = 46;
const int squareradius = 20;Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->setFixedHeight(600);this->setFixedWidth(800);m_value = 0;m_offsetPoint = QPoint(0, 0);ui->widget->installEventFilter(this);this->initForm();
}Widget::~Widget()
{delete ui;
}void Widget::initForm()
{QTimer::singleShot(10, this, SLOT(onUpdateWidget()));connect(ui->horizontalSlider, &QSlider::valueChanged, this, &Widget::onSliderValueChanged);connect(ui->horizontalSlider, &QSlider::sliderReleased, this, &Widget::onSliderReleased);m_pixmap = QString("H:\\picture\\TorchLight\\TorchLight0.bmp");QTimer::singleShot(100, this, SLOT(onUpdatePixmap()));}void Widget::onUpdateWidget()
{ui->horizontalSlider->setRange(0, ui->widget->width() - squarewidth);
}void Widget::onUpdatePixmap()
{m_offsetPoint.rx() = qBound(0, QRandomGenerator::global()->bounded(1024*10) % this->width() + squarewidth + squareradius,this->width() - squarewidth);m_offsetPoint.ry() = qBound(0, QRandomGenerator::global()->bounded(1024*10) % ui->widget->height() + squarewidth + squareradius,ui->widget->height() - squarewidth - squareradius);qDebug()<<m_offsetPoint.rx()<<m_offsetPoint.ry();this->update();
}void Widget::onSliderValueChanged(int value)
{//ui->widget->setValue(value);m_value = qBound(0, value, ui->widget->width() - squarewidth);update();
}void Widget::onSliderReleased()
{bool isOverlap = qAbs(-m_offsetPoint.x() + m_value) < 5;QString content = isOverlap ? "验证成功!" : "验证失败!";QMessageBox msgBox;msgBox.setWindowTitle("滑块图片验证");msgBox.setText(content);msgBox.exec();}void Widget::drawPicture()
{QPainter painter(ui->widget);painter.setRenderHint(QPainter::Antialiasing);QPainterPath clippath;clippath.addRoundedRect(ui->widget->rect(), 4, 4);painter.setClipPath(clippath);//画背景图const QPixmap & pixmap = QPixmap(m_pixmap).scaled(ui->widget->width(), ui->widget->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);painter.drawPixmap(0, 0, ui->widget->width(), ui->widget->height(), pixmap);QPainterPath cutoutpath;cutoutpath.setFillRule(Qt::WindingFill);QRect rect(m_offsetPoint, QSize(squarewidth, squarewidth));cutoutpath.addEllipse(rect);//画被扣除的空白区域QPainterPath subellipsepath;subellipsepath.addEllipse(rect.x(), rect.y() - rect.height() / 2, rect.width(), rect.height());cutoutpath = cutoutpath.united(subellipsepath);painter.setPen(QPen(QColor(80, 80, 80), 1));painter.setBrush(QColor(200, 200, 200, 220));painter.drawPath(cutoutpath);//画滑块图片QPixmap puzzlePixmap(ui->widget->size());puzzlePixmap.fill(Qt::transparent);QPainter puzzlePainter(&puzzlePixmap);puzzlePainter.setRenderHints(QPainter::Antialiasing);puzzlePainter.setClipPath(cutoutpath);puzzlePainter.setPen(QPen(QColor(229, 228, 228), 2));puzzlePainter.drawPixmap(0, 0, ui->widget->width(), ui->widget->height(), pixmap);puzzlePainter.drawPath(cutoutpath);painter.drawPixmap(-m_offsetPoint.x() + m_value, 0, ui->widget->width(), ui->widget->height(), puzzlePixmap);}bool Widget::eventFilter(QObject *watched, QEvent *event)
{if (watched == ui->widget && event->type() == QEvent::Paint){drawPicture();return true;}return QWidget::eventFilter(watched, event);
}void Widget::paintEvent(QPaintEvent *)
{}

QSlider的样式表

 QSlider::groove:horizontal {border: 1px solid #999999;height: 10px; /* the groove expands to the size of the slider by default. by giving it a height, it has a fixed size */background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c004);margin: 2px 0;}QSlider::handle:horizontal {background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #8f0f8f);border: 1px solid #5c0c5c;width: 18px;margin: -12px 0; /* handle is placed by default on the contents rect of the groove. Expand outside the groove */border-radius: 3px;}

空白区域画法

在painter中绘制一个封闭的painterpath。path中的路径通过添加形状的方式自己设置。背景色通过setBrush设置。

QPainterPath cutoutpath;
cutoutpath.setFillRule(Qt::WindingFill);
QRect rect(m_offsetPoint, QSize(squarewidth, squarewidth));
cutoutpath.addEllipse(rect);//画被扣除的空白区域
QPainterPath subellipsepath;
subellipsepath.addEllipse(rect.x(), rect.y() - rect.height() / 2, rect.width(), rect.height());
cutoutpath = cutoutpath.united(subellipsepath);painter.setPen(QPen(QColor(80, 80, 80), 1));
painter.setBrush(QColor(200, 200, 200, 220));
painter.drawPath(cutoutpath);

形状可以任意修改

//画被扣除的空白区域QPainterPath cutoutpath;cutoutpath.setFillRule(Qt::WindingFill);QRect rect(m_offsetPoint, QSize(squarewidth, squarewidth));cutoutpath.addEllipse(rect);cutoutpath.addRect(QRect(m_offsetPoint.x() + squarewidth/2, m_offsetPoint.y() + squarewidth/2, squarewidth, squarewidth));painter.setPen(QPen(QColor(80, 80, 80), 1));painter.setBrush(QColor(200, 200, 200, 220));painter.drawPath(cutoutpath);

填充规则

QPainterPath中setFillRule()共有两个填充规则:Qt::OddEvenFillQt::WindingFill

其中,Qt::OddEvenFill使用的是奇偶填充规则,具体来说就是:如果要判断一个点是否在图形中,那么可以从该点向图形外引一条水平线﹐如果该水平线与图形的交点的个数为奇数,那么该点就在图形中。这个规则是默认值;

Qt::WindingFill使用的是非零弯曲规则,具体来说就是:如果要判断一个点是否在图形中,那么可以从该点向图形外引一条水平线,如果该水平线与图形的边线相交,这个边线是顺时针绘制的,就记为1;是逆时针绘制的就记为-1。然后将所有数值相加,如果结果不为0,那么该点就在图形中。


对于Qt::OddEvenFill规则,第一个交点记为1,第二个交点记为2;
对于Qt::WindingFill规则,因为椭圆和矩形都是以顺时针进行绘制的,所以各个交点对应的边都使用1来代表。

滑块图片画法

注意puzzlePainter指向puzzlePixmap,puzzlePixmap是个透明图,在里面绘制同上方空白区域的painterpath可见,然后合并图片和空白区域的painter。

QPixmap puzzlePixmap(ui->widget->size());puzzlePixmap.fill(Qt::transparent);QPainter puzzlePainter(&puzzlePixmap);puzzlePainter.setRenderHints(QPainter::Antialiasing);puzzlePainter.setClipPath(cutoutpath);puzzlePainter.setPen(QPen(QColor(229, 228, 228), 2));puzzlePainter.drawPixmap(0, 0, ui->widget->width(), ui->widget->height(), pixmap);puzzlePainter.drawPath(cutoutpath);painter.drawPixmap(-m_offsetPoint.x() + m_value, 0, ui->widget->width(), ui->widget->height(), puzzlePixmap);

关键字:QT滑块图片验证程序

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: