QT滑块图片验证程序

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

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    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);

滑块图片画法

注意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);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/780070.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

物联网的技术和应用有哪些?

随着科技的飞速发展&#xff0c;物联网已经成为连接世界的重要纽带&#xff0c;塑造着我们未来的生活。我们一起深入探索物联网的前沿技术和前瞻性应用&#xff0c;一窥未来的可能性。 获取物联网解决方案&#xff0c;YesPMP平台一站式物联网开发服务。 提示&#xff1a;智慧家…

Google Earth Engine(GEE)——ui.Panel添加到地图上

结果 函数 ui.root.add(widget) 将一个widget添加到根面板上。 返回根面板。 参数。 widget&#xff08;ui.Widget&#xff09;。 要添加的widget。 返回&#xff1a; ui.Panel 代码 //label var label ui.Label({ value: "text label", style: {fontSi…

java 公共字段填充

公共字段填充 1、mybatis-plus2、mybatis 使用注解加aop2.1 自定义注解2.2 自定义切面类2.3 在mapper上添加上自定义的注解 1、mybatis-plus 通过在类上使用如下的注解 TableField(fill FieldFill.INSERT) 是 MyBatis-Plus 中的注解&#xff0c;用于自动填充字段的值。MyBat…

上海外贸建站公司wordpress模板推荐

Sora索啦高端制造业wordpress主题 红色高端制造业wordpress主题&#xff0c;适合外贸企业出海建独立站的wordpress模板。 https://www.jianzhanpress.com/?p5885 Yamal外贸独立站wordpress主题 绿色的亚马尔Yamal外贸独立站wordpress模板&#xff0c;适用于外贸公司建独立站…

【HBZ】高性能zeroCopy零拷贝与普通IO差距与原理

简介 随着IO不断地发展&#xff0c;无论哪种拷贝方式&#xff0c;DMA从磁盘拷贝数据到内核缓冲区&#xff0c;都会拷贝多一些数据, 不会只拷贝用户态的指定size的数据&#xff0c;而是会将目标数据的临近数据也都拷贝到内核缓冲区&#xff0c;以便下次IO操作可以直接从内核缓冲…

【Android】自定义换肤框架05之Skinner框架集成

引入依赖 api("io.github.hellogoogle2000:android-skinner:1.0.0")初始化Skinner 在所有功能前调用即可&#xff0c;建议在Application中初始化 SkinnerKit.init(application)安装皮肤包 在应用该皮肤包前安装即可&#xff0c;建议预安装&#xff0c;或应用皮肤…

解决后端限制导致前端配置跨域仍请求失败报504的问题

文章目录 问题一、通过配置跨域方式二、直接真实接口请求三、解决方式四、后端这样做的原因 总结 问题 前端项目设置跨域proxy处理&#xff0c;接口请求不会报跨域&#xff0c;但是接口请求报了504&#xff0c;这种情况如何处理呢&#xff0c;后端又为何要这么做&#xff0c;下…

生成式AI的短板在于“Token”的存在

生成式AI模型处理文本的方式与人类不同。理解它们基于“token”的内部环境&#xff0c;可能有助于解释一些奇怪行为和固有局限性。 从小型设备上的Gemma到OpenAI领先行业的GPT-4o&#xff0c;大多数模型都是基于一种称为Transformer的架构。由于Transformer在将文本与其他类型…

前端初学java二(类、多态、接口、内部类、泛型)

目录 类 种类 Javabean类 测试类 工具类 类的初始化 构照函数 新建对象的内存图 static 继承 This Super 虚方法表 Override 修饰符权限 构造代码块 静态代码块 多态 前提 优点 缺点 示例 抽象方法 抽象类 接口 implements 继承 内部类 成员内部类…

系统化学习 H264视频编码(02) I帧 P帧 B帧 引入及相关概念解读

说明&#xff1a;我们参考黄金圈学习法&#xff08;什么是黄金圈法则?->模型 黄金圈法则&#xff0c;本文使用&#xff1a;why-what&#xff09;来学习音H264视频编码。本系列文章侧重于理解视频编码的知识体系和实践方法&#xff0c;理论方面会更多地讲清楚 音视频中概念的…

【机器学习】机器学习重塑广告营销:精准触达,高效转化的未来之路

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀目录 &#x1f4d2;1. 引言&#x1f4d9;2. 机器学习基础与广告营销的结合&#x1f9e9;机器学习在广告营销中的核心应用领域&#x1f339;用…

cf 7.7

Problem - C - Codeforces 大致意思&#xff1a; 找前缀&#xff0c;排序后使得本位之前数字和等于该位 &#xff08;以下代码超时了&#xff09; #include<bits/stdc.h> typedef long long ll;#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0) const ll …

阿里云存储应用

如何做好权限控制 小浩在梳理门户网站静态资源时&#xff0c;发现有些资源是仅内部员工可访问&#xff0c;有些资源是特定的注册客户可访问&#xff0c;还有些资源是匿名客户也可以访问。针对不同场景、不同用户&#xff0c;小浩该如何规划企业门户网站静态资源的权限控制呢&a…

MySQL第三次作业--DML语句(INSERT)

目录 一、在数据库中创建一个表student&#xff0c;用于存储学生信息 二、向student表中添加一条新记录&#xff0c;记录中id字段的值为1&#xff0c;name字段的值为"monkey"&#xff0c;grade字段的值为98.5 三、向student表中添加多条新记录&#xff1a; 2,&qu…

Docker 容器网络及其配置说明

Docker 容器网络及其配置说明 docker容器网络docker的4种网络模式bridge 模式container模式host 模式none 模式应用场景 docker 容器网络配置Linux 内核实现名称空间的创建创建 Network Namespace操作 Network Namespace 转移设备veth pair创建 veth pair实现 Network Namespac…

缓存-分布式锁-原理和基本使用

分布式锁原理和使用 自旋 public Map<String, List<Catelog2Vo>> getCatalogJsonFromDBWithRedisLock() {Boolean b redisTemplate.opsForValue().setIfAbsent(Lock, Lock, Duration.ofMinutes(1));if (!b) {int i 10;while (i > 0) {Object result redisTe…

【QT】容器类控件

目录 概述 Group Box 核心属性 Tab Widget 核心属性 核心信号 核心方法 使用示例&#xff1a; 布局管理器 垂直布局 核心属性 使用示例&#xff1a; 水平布局 核⼼属性 (和 QVBoxLayout 属性是⼀致的) 网格布局 核心属性 使用示例&#xff1a; 示例&#x…

【python】python猫眼电影数据抓取分析可视化(源码+数据集+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

安卓虚拟位置修改

随着安卓系统的不断更新&#xff0c;确保软件和应用与最新系统版本的兼容性变得日益重要。本文档旨在指导用户如何在安卓14/15系统上使用特定的功能。 2. 系统兼容性更新 2.1 支持安卓14/15&#xff1a;更新了对安卓14/15版本的支持&#xff0c;确保了软件的兼容性。 2.2 路…

Xilinx FPGA:vivado串口输入输出控制fifo中的数据

一、实验要求 实现同步FIFO回环测试&#xff0c;通过串口产生数据&#xff0c;写入到FIFO内部&#xff0c;当检测到按键信号到来&#xff0c;将FIFO里面的数据依次读出。 二、信号流向图 三、状态转换图 四、程序设计 &#xff08;1&#xff09;按键消抖模块 timescale 1ns…