当前位置: 首页 > ds >正文

QT之头像剪裁效果实现

文章目录

  • 源码地址,环境: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.xdnf.cn/news/10709.html

相关文章:

  • 排序算法——详解
  • pikachu靶场通关笔记10 XSS关卡06-XSS之盲打
  • python打卡day43@浙大疏锦行
  • 定制开发开源AI智能名片驱动下的海报工厂S2B2C商城小程序运营策略——基于社群口碑传播与子市场细分的实证研究
  • 【Linux】Git原理与使用
  • MCP协议学习
  • 《Effective Python》第六章 推导式和生成器——将迭代器作为参数传递给生成器,而不是调用 send 方法
  • 【兽医处方专用软件】佳易王兽医电子处方软件:高效智能的宠物诊疗管理方案
  • 腾讯云 Python3.12.8 通过yum安装 并设置为默认版本
  • [android]MT6835 Android 指令启动MT6631 wifi操作说明
  • Android第十二次面试GetX库渲染机制
  • SpringBoot-Thymeleaf
  • React 18 生命周期详解与并发模式下的变化
  • 《深入解析SPI协议及其FPGA高效实现》-- 第二篇:SPI控制器FPGA架构设计
  • 【学习笔记】On the Biology of a Large Language Model
  • 前端八股之Vue
  • 三种经典算法优化无线传感器网络(WSN)覆盖(SSA-WSN、PSO-WSN、GWO-WSN),MATLAB代码实现
  • 刘克清因“长相违规”而困扰
  • Linux入门(十三)动态监控系统监控网络状态
  • 【Linux】基础文件IO
  • 如何自动部署GitLab项目
  • 【C++】类的析构函数
  • Axure 基础入门
  • 【Linux】网络--网络层--IP协议
  • JavaSE知识总结 ~个人笔记以及不断思考~持续更新
  • 短视频平台差异视角下开源AI智能名片链动2+1模式S2B2C商城小程序的适配性研究——以抖音与快手为例
  • debian12操作系统apt命令出现无法安全的用该源更新解决方案
  • 池中锦鲤的自我修养,聊聊蓄水池算法
  • 4、ubuntu系统 | 文本和目录操作函数
  • 结构型设计模式之桥接模式