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

Qt QML实现鼠标自由选择不规则区域进行截图

背景

不规则区域进行截图是一种常见的应用场景,通常用于程序截图工具或者图像处理软件中。主要是为了让用户可以自由选择任意形状的区域进行截图,而不仅仅局限于矩形区域。这样用户可以更灵活地进行截图操作,特别是对于需要截取特定形状区域的情况下非常实用。

通过实现鼠标自由选择不规则区域进行截图,用户可以更精确地选择需要截取的内容,避免不必要的部分被包含在截图中。

效果

先来看下运行效果:
在这里插入图片描述
截图效果:
在这里插入图片描述

在这里插入图片描述
可以看到,截图内容是根据鼠标自由选区来截取不规则的图形,其他区域为透明的。

关键代码

实现逻辑是在QML中鼠标选区记录坐标点,然后截取整个屏幕画面,根据坐标点将图片内容拷贝出来生成新的图片。

保存部分的代码:

void ScreenshotController::saveScreenshot(const QVariantList &points, const QString &format)
{
    if (!m_isCapturing || points.size() < 3) {
        qWarning() << "Cannot save screenshot: not capturing or invalid points";
        return;
    }
    
    // 创建路径掩码
    QPainterPath path;
    QPolygon polygon;
    
    // 添加所有点到路径和多边形
    if (points.size() > 0) {
        QPointF firstPoint = points[0].toPointF();
        path.moveTo(firstPoint);
        polygon << QPoint(firstPoint.x(), firstPoint.y());
        
        for (int i = 1; i < points.size(); i++) {
            QPointF p = points[i].toPointF();
            path.lineTo(p);
            polygon << QPoint(p.x(), p.y());
            qDebug() <<__FUNCTION__<< "point=" << p;
        }
        
        // 闭合路径
        path.closeSubpath();
    }

    // 获取选区的边界矩形
    QRect boundingRect = polygon.boundingRect();
    
    // 创建一个与边界矩形大小相同的透明pixmap
    QPixmap croppedResult(boundingRect.size());
    croppedResult.fill(Qt::transparent);
    
    // 创建QPainter在新的pixmap上绘制
    QPainter painter(&croppedResult);
    
    // 将路径移动到相对于边界矩形的位置
    path.translate(-boundingRect.topLeft());
    
    // 设置剪切路径,只绘制路径内的内容
    painter.setClipPath(path);
    
    // 绘制原始截图的对应部分
    painter.drawPixmap(0, 0, m_originalPixmap, boundingRect.x(), boundingRect.y(), boundingRect.width(), boundingRect.height());
    
    // 结束绘制
    painter.end();

    // 生成默认文件名
    QString defaultFileName = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + 
                             "/screenshot_" + 
                             QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss") + 
                             "." + format.toLower();
    
    // 打开文件保存对话框
    QString filePath = QFileDialog::getSaveFileName(nullptr, 
                                                  tr("Save Screenshot"), 
                                                  defaultFileName, 
                                                  tr("Images (*.%1)").arg(format.toLower()));
    
    if (!filePath.isEmpty()) {
        // 保存截图
        if (croppedResult.save(filePath, format.toUtf8().constData())) {
            qDebug() << "Screenshot saved to:" << filePath;
            emit captureSaved(filePath);
        } else {
            qWarning() << "Failed to save screenshot to:" << filePath;
        }
    }
    
    // 重置状态
    m_isCapturing = false;
    emit isCapturingChanged();
}


源代码下载

相关文章:

  • 编程自学指南:java程序设计开发,Java I/O流,为什么需要I/O流?,Java I/O体系结构,字节流,字符流,对象流与序列化
  • 深入理解Spring Boot:快速构建现代化的Java应用
  • C++中,存储持续性、作用域和链接性
  • 一般机器学习有哪些算法?
  • python笔记2
  • LeeCode题库第643题
  • 用Maven创建只有POM文件的项目
  • MCU的工作原理:嵌入式系统的控制核心
  • 解决 Docker 镜像拉取超时问题:配置国内镜像源
  • 【深度学习|目标检测】YOLO系列anchor-based原理详解
  • 注意力机制,层归一化,RBA。KAN-ODE,小波KAN
  • 提升开发效率的FPGA/IC小工具
  • 文件解析漏洞详解
  • 微软 System Center Configuration Manager(SCCM)的组件文件
  • Python中可调用对象的意义和用途
  • C++类和对象(中) 之 【运算符重载、赋值运算符重载、前置++与后置++、const成员、取地址及const取地址操作符重载】
  • SmartFormat:轻量级文本模板库,轻松替代 string.Format
  • MyBatis 的一级、二级缓存
  • LoRa无线技术解析
  • Flutter开发鸿蒙的项目已经迁移到gitcode了
  • 李国英:数智化建设推动大坝实现更安全运行、更精准调度
  • “图像证史”又添新作,800余幅历史图片展现光华大学办学历程
  • 预算1600万寻装修供应商,济宁银行山东省内第八家分行将落户济南
  • 马上评|当众猥亵女演员,没有任何开脱理由
  • 萨洛宁、康托罗夫、长野健……7月夏季音乐节来很多大牌
  • 两次通话、三点诉求,泽连斯基对美称愿与俄签署和平备忘录