QT之头像剪裁效果实现

news2025/6/5 18:05:02

文章目录

  • 源码地址,环境:QT5.15,MinGW32位
  • 效果演示
  • 导入图片
  • 设置剪裁区域
  • 创建剪裁小窗口
  • 重写剪裁小窗口的鼠标事件
    • mousePressEvent
    • mouseMoveEvent
    • mouseReleaseEvent
  • 小窗口移动触发父窗口的重绘事件
  • 剪裁效果实现

源码地址,环境:QT5.15,MinGW32位

效果演示

在这里插入图片描述
在这里插入图片描述

导入图片

    QPixmap m_srcPix;
    QPixmap m_scaledPix;
    //从文件导入图片
    m_srcPix.load("D:\\Jolly\\A_0voice_chat\\chapter_explanation\\PictureEdit_demo\\PictureEdit\\images\\1.png");
    //把导入的图片截取到窗口大小
    m_scaledPix = m_srcPix.scaled(ui->label->width(), ui->label->height());
    //在窗口显示图片
    ui->label->setPixmap(m_scaledPix);

设置剪裁区域

    //裁剪头像活动窗口
    //设置透明
    this->setWindowFlags(Qt::FramelessWindowHint);

    //设置矩形区域,整个窗口
    this->setGeometry(0, 0, parentWidget()->width(), parentWidget()->height());

	CutDialog *m_cutDialog;
    //头像剪切窗口
    m_cutDialog = new CutDialog(this);
    m_cutDialog->show();

创建剪裁小窗口

CutDialog::CutDialog(QWidget *parent) :
    QWidget(parent)
{
    setGeometry(0,0, 150, 150);

    m_mouseDown = false;
}

重写剪裁小窗口的鼠标事件

mousePressEvent

void CutDialog::mousePressEvent(QMouseEvent *event)
{
    //获取鼠标按下时的位置
    m_startPoint = event->pos();
    //判断按下的是否是鼠标左键
    m_mouseDown = event->button() == Qt::LeftButton;
}

mouseMoveEvent

要是没有启用鼠标追踪,mouseMoveEvent 只有在鼠标按键被按下并且鼠标移动时才会触发,而且是在mousePressEvent触发之后。
当启用鼠标追踪后,不管鼠标按键是否被按下,只要鼠标移动,mouseMoveEvent就会触发

void CutDialog::mouseMoveEvent(QMouseEvent *event)
{
    //获取鼠标移动以后的位置
    QPoint dragPoint = event->pos();

    if (m_mouseDown) {
        //pos保存小部件在其父部件中的位置
        QPoint p = QPoint(
            //pos() 是对话框在父窗口中的左上角坐标
            //dragPoint - m_startPoint 计算鼠标移动的偏移量
            //原理: 拖动点相对于对话框的位置保持不变(如从(10,10)点开始拖动,移动后仍抓住该点)
            pos().x()+dragPoint.x() - m_startPoint.x(), // 水平方向
            pos().y()+dragPoint.y()-m_startPoint.y()    // 垂直方向
        );

        QPoint dragEndge = p;
        dragEndge.setX(p.x() + rect().width());   // 对话框右下角X坐标
        dragEndge.setY(p.y() + rect().height());  // 对话框右下角Y坐标

        //左上角约束,保证小窗口左上角在父窗口范围内
        p.setX(p.x() < 0 ? 0 : p.x());
        p.setY(p.y() < 0 ? 0 : p.y());

        //右下角约束
        // 确保右下角X ≤ 父窗口宽度
        p.setX(dragEndge.x() > parentWidget()->width()
                   ? parentWidget()->width() - rect().width()
                   : p.x());

        // 确保右下角Y ≤ 父窗口高度
        p.setY(dragEndge.y() > parentWidget()->height()
                   ? parentWidget()->height() - rect().height()
                   : p.y());


        //QWidget::move() 对窗口部件的位置进行设置
        move(p);
/*
move函数原型
void move(int x, int y);
void move(const QPoint &pos);
 */
    }

}

mouseReleaseEvent

释放鼠标时将m_mouseDown 设置为false,避免鼠标右键或其他案件误触发mouseMoveEvent

void CutDialog::mouseReleaseEvent(QMouseEvent *event)
{
    m_mouseDown = false;
}

小窗口移动触发父窗口的重绘事件

paintEvent调用时机:

​​首次显示窗口时​​
当 PhotoShotDialog 首次显示(例如通过 show() 或 exec())时,系统会自动触发 paintEvent 进行初始绘制。

​​窗口需要重绘时​​
窗口被其他窗口遮挡后重新暴露出来
窗口内容发生变化(如子窗口移动、尺寸变化)
调用 update() 或 repaint() 方法强制重绘

​​子窗口移动时(关键)​​
当用户拖动 CutDialog时:
CutDialog::mouseMoveEvent() 中调用了 move§ 移动裁剪框
移动操作会​​自动触发父窗口(PhotoShotDialog)的重绘​​,因为:
子窗口位置变化导致父窗口的可见区域需要更新
系统自动发送重绘事件到父窗口

void PhotoShotDialog::paintEvent(QPaintEvent *event)
{
    QPainterPath painterPath;
    QPainterPath p;
    p.addRect(x(),y(),this->rect().width(), this->rect().height()); //裁剪头像活动窗口 (蓝色矩形)
    //QWidget::geometry()返回一个 QRect 对象。这个对象包含了窗口部件的位置和大小信息
    painterPath.addRect(m_cutDialog->geometry()); //头像剪切窗口 (紫色矩形)

    QPainterPath drawPath = p.subtracted(painterPath); //subtracted 获取除了painterPath区域以外的窗口
    QPainter painter(this);
    painter.setOpacity(0.6); //设置Qt控件透明度 0表示全透明,1表示不透明
    painter.fillPath(drawPath, QBrush(Qt::black));
}

剪裁效果实现

void PictureEdit::on_pushButton_clicked()
{
    //直接复制小窗口的图像内容
    QPixmap pix = m_scaledPix.copy(m_psDialog->getCutGeometry());

    //将截图内容重命名,并保存到指定目录
    pix.save("D:\\work\\workspace\\qtstudyspace\\PictureEdit\\images\\cut.png", "png");
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【GPT入门】第40课 vllm与ollama特性对比,与模型部署

【GPT入门】第40课 vllm与ollama特性对比&#xff0c;与模型部署 1.两种部署1.1 vllm与ollama特性对比2. vllm部署2.1 服务器准备2.1 下载模型2.2 提供模型服务 1.两种部署 1.1 vllm与ollama特性对比 2. vllm部署 2.1 服务器准备 在autodl 等大模型服务器提供商&#xff0c;…

unity开发棋牌游戏

使用unity开发的棋牌游戏&#xff0c;目前包含麻将、斗地主、比鸡、牛牛四种玩法游戏。 相关技术 客户端&#xff1a;unity 热更新&#xff1a;xlua 服务器&#xff1a;c Web服务器&#xff1a;ruoyi 游戏视频 unity开发棋牌游戏 游戏截图

Nat Commun项目文章 ▏小麦CUTTag助力解析转录因子TaTCP6调控小麦氮磷高效利用机制

今年2月份发表在《Nature Communications》&#xff08;IF14.4&#xff09;的“TaTCP6 is required for efficientand balanced utilization of nitrate and phosphorus in wheat”揭示了TaTCP6在小麦氮磷利用中的关键调控作用&#xff0c;为优化肥料利用和提高作物产量提供了理…

C 语言开发中常见的开发环境

目录 1.Dev-C 2.Visual Studio Code 3.虚拟机 Linux 环境 4.嵌入式 MCU 专用开发环境 1.Dev-C 使用集成的 C/C 开发环境&#xff08;适合基础学习&#xff09;,下载链接Dev-C下载 - 官方正版 - 极客应用 2.Visual Studio Code 结合 C/C 扩展 GCC/MinGW 编译器&#xff0c…

vscode命令行debug

vscode命令行debug 一般命令行debug会在远程连服务器的时候用上&#xff0c;命令行debug的本质是在执行时暴露一个监听端口&#xff0c;通过进入这个端口&#xff0c;像本地调试一样进行。 这里提供两种方式&#xff1a; 直接在命令行中添加debugpy&#xff0c;适用于python…

Matlab作图之 subplot

1. subplot(m, n, p) 将当前图形划分为m*n的网格&#xff0c;在 p 指定的位置创建坐标轴 matlab 按照行号对子图的位置进行编号 第一个子图是第一行第一列&#xff0c;第二个子图是第二行第二列......... 如果指定 p 位置存在坐标轴&#xff0c; 此命令会将已存在的坐标轴设…

【机器学习基础】机器学习入门核心算法:层次聚类算法(AGNES算法和 DIANA算法)

机器学习入门核心算法&#xff1a;层次聚类算法&#xff08;AGNES算法和 DIANA算法&#xff09; 一、算法逻辑二、算法原理与数学推导1. 距离度量2. 簇间距离计算&#xff08;连接标准&#xff09;3. 算法伪代码&#xff08;凝聚式&#xff09; 三、模型评估1. 内部评估指标2. …

Google Play的最新安全变更可能会让一些高级用户无法使用App

喜欢Root或刷机的Android用户要注意了&#xff0c;Google最近全面启用了新版Play Integrity API&#xff0c;可能会导致部分用户面临无法使用某些App的窘境。Play Integrity API是Google提供给开发者的工具&#xff0c;用于验证App是否在“未修改”的设备上运行。 许多重要应用…

React---day5

4、React的组件化 组件的分类&#xff1a; 根据组件的定义方式&#xff0c;可以分为&#xff1a;函数组件(Functional Component )和类组件(Class Component)&#xff1b;根据组件内部是否有状态需要维护&#xff0c;可以分成&#xff1a;无状态组件(Stateless Component )和…

Java开发之定时器学习

面试 一、线程池实现定时器 核心代码&#xff1a; public static void main(String[] args) {ScheduledExecutorService scheduledExecutorService Executors.newScheduledThreadPool(5);Runnable runnable () -> System.out.println("当前线程"Thread.current…

HealthBench医疗AI评估基准:技术路径与核心价值深度分析(上)

引言:医疗AI评估的新范式 在人工智能技术迅猛发展的当下,医疗AI系统已逐渐从实验室走向临床应用。然而,医疗领域的特殊性要求这些系统不仅需要在技术指标上表现出色,更需要在实际临床场景中展现出可靠、安全且有效的性能。长期以来,医疗AI评估领域面临着三个核心挑战:评…

Windows+VSCode搭建小智(xiaozhi)开发环境

作为一名DIY达人&#xff0c;肯定不会错过最近很火的“小智AI聊天机器人”&#xff0c;网上教程非常丰富&#xff0c;初级玩家可以直接在乐鑫官方下载ESP-IDF安装包并经过简单的菜单式配置后&#xff0c;即可进行代码编译和烧录&#xff08;详见&#xff1a;Docs&#xff09;。…

VueScan Pro v9.8.45.08 一款图像扫描软件,中文绿色便携版

VueScan是著名的第三方底片扫描仪驱动程序&#xff0c;支持市场可见绝大多数型号的底片扫描仪&#xff0c;可以更为灵活地控制扫描过程&#xff0c;更深入地发掘硬件潜力&#xff0c;获取色彩 完美的高质量扫描结果。VueScan支持200种以上的底片类型&#xff0c;在剪取图像时制…

FreeRTOS通俗理解指南:基础概念 + 架构+ 内核组件+练手实验

RTOS 基础概念 想象一下&#xff0c;你是一个忙碌的厨师&#xff0c;在厨房里同时要完成煎牛排和煮意大利面两项任务。 1.传统单线程模式&#xff08;没有RTOS&#xff09; 如果你只能按顺序一项一项地做&#xff0c;就会是这样的过程&#xff1a; 先煎一会儿牛排然后去看看…

房屋租赁系统 Java+Vue.js+SpringBoot,包括房屋信息、看房申请、租赁合同、房屋报修、收租信息、维修数据、租客管理、公告管理模块

房屋租赁系统 JavaVue.jsSpringBoot&#xff0c;包括房屋信息、看房申请、租赁合同、房屋报修、收租信息、维修数据、租客管理、公告管理模块 百度云盘链接&#xff1a;https://pan.baidu.com/s/16YRGBPsfbd4_HxXhO0jM5Q 密码&#xff1a;smk4 摘 要 房屋是人类生活栖息的重要…

ASP.NET MVC添加视图示例

ASP.NET MVC高效构建Web应用- 商品搜索 - 京东 视图&#xff08;V&#xff09;是一个动态生成HTML页面的模板&#xff0c;它负责通过用户界面展示内容。本节将修改HelloWorldController类&#xff0c;并使用视图模板文件&#xff0c;以干净地封装生成对客户端的HTML响应的过程…

50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | Form Wave(表单label波动效果)

&#x1f4c5; 我们继续 50 个小项目挑战&#xff01;—— FormWave组件 仓库地址&#xff1a;https://github.com/SunACong/50-vue-projects 项目预览地址&#xff1a;https://50-vue-projects.vercel.app/ &#x1f3af; 组件目标 构建一个美观、动态的登录表单&#xff0…

双目相机深度的误差分析(基线长度和相机焦距的选择)

全文基于针孔模型和基线水平放置来讨论 影响双目计算深度的因素&#xff1a; 1、基线长度&#xff1a;两台相机光心之间距离2、相机焦距&#xff08;像素&#xff09;&#xff1a; f x f_x fx​&#xff08;或 f y f_y fy​&#xff09;为焦距 f f f和一个缩放比例的乘积。在…

Pytorch Geometric官方例程pytorch_geometric/examples/link_pred.py环境安装教程及图数据集制作

最近需要训练图卷积神经网络&#xff08;Graph Convolution Neural Network, GCNN&#xff09;&#xff0c;在配置GCNN环境上总结了一些经验。 我觉得对于初学者而言&#xff0c;图神经网络的训练会有2个难点&#xff1a; ①环境配置 ②数据集制作 一、环境配置 我最初光想…

React---day6、7

6、组件之间进行数据传递 **6.1 父传子&#xff1a;**props传递属性 父组件&#xff1a; <div><ChildCpn name"蒋乙菥" age"18" height"1,88" /> </div>子组件&#xff1a; export class ChildCpn extends React.Component…