首页 > 其他分享 >Qt之截图存为图片或PDF打印(七)

Qt之截图存为图片或PDF打印(七)

时间:2024-12-16 19:32:38浏览次数:5  
标签:beginPoint 截图 Qt void PrintScreen PDF event

Qt开发 系列文章 - Screenshot-To-PicOrPDF(七)


目录

前言

一、截图

二、功能实现

1.创建项目

2.新建类

3.编写类

1.定义头文件

2.相关功能函数

3.使用类

总结


前言

本文利用Qt平台,实现屏幕截图功能,并将截图复制、保存为图片、或打印到PDF中。


一、截图

要实现Qt的截图功能,主要是要调用Qt自带的QScreen类,该类作用是用于获取屏幕信息并进行屏幕截图。利用QApplication方法获取所有屏幕的信息,然后通过QScreen类的grabWindow函数捕获整个屏幕或指定窗口。

二、功能实现

1.创建项目

本文示例项目为上一篇博文Qt之点击鼠标右键创建菜单栏使用(六)-CSDN博客,在此项目基础上进行扩展的,主要添加了截图功能,并将其封装为一个类,用户可调用该类实现截图。

2.新建类

新建的类主要是实现截图功能,在原项目基础上添加。首先在Qt上打开项目,点击项目右键选择添加新文件add new file,如下图所示。

然后打开,按如下选择:

创建类的名称为PrintScreen,选择继承类QWidget,如下所示。

创建完毕后,会在项目上看见添加的这两个文件,头文件和源文件,如下所示。

  

3.编写类

1.定义头文件

打开创建的头文件,添加引用的头文件代码、以及定义相关变量,相关代码如下。

extern QList<QPixmap> pixmaps;
/**
 * @brief The PrintScreen class
 * @param 区域截屏功能
 */
class PrintScreen : public QWidget
{
    Q_OBJECT
public:
    PrintScreen(QWidget *parent = nullptr);
    ~PrintScreen();
private:
    /**
     * @brief 初始化截图窗口的背景和尺寸
     */
    void InitWindow(void);
    void CreateMenu(void);
    /**
     * @brief 根据起始点和终止点计算矩形区域
     * @param beginPoint 矩形区域的起始点
     * @param endPoint 矩形区域的终止点
     * @return 返回根据两点计算出的 QRect 对象
     */
    QRect GetRect(const QPoint &beginPoint, const QPoint &endPoint);

protected:
    // 事件处理方法
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent* event);
    void mouseReleaseEvent(QMouseEvent *event);
    void keyPressEvent(QKeyEvent *event);
    void paintEvent(QPaintEvent *event);
    QPixmap copytoPasteboard(bool hideflag); //将截图复制到粘贴板
    void savetoImage(void);                  //截图保存到图片
    void copytoPDF(void);                    //截图复制到文档
    void printtoPDF(void);                   //将制到文档的截图打印出来
    void saveImage(void);
private:
    // 成员变量
    bool m_isMousePress = false;     // 是否按下鼠标
    bool m_captureComplete = false;  // 截图是否完成
    bool m_isDragging = false;       // 是否正在拖动截图区域
    QPixmap m_loadPixmap;    // 加载的屏幕截图
    QPixmap m_capturePixmap; // 截取的屏幕区域
    int m_screenWidth;       // 屏幕宽度
    int m_screenHeight;      // 屏幕高度
    QPoint m_beginPoint;     // 截图开始点
    QPoint m_endPoint;       // 截图结束点
    QPoint m_dragPosition;   // 拖动时的鼠标位置
    QPainter m_painter;      // 绘图器对象
    QMenu *menu;
};

2.相关功能函数

打开创建的源文件,实现相关功能函数。

第一个函数,功能实现截图初始化,捕捉屏幕,放在该类的构造函数处被调用,代码如下。

void PrintScreen::InitWindow(void)
{
    // 启用鼠标跟踪
    this->setMouseTracking(true);
    // 设置无边框窗口
    this->setWindowFlags(Qt::FramelessWindowHint);
    // 设置窗口为激活状态和全屏模式
    setWindowState(Qt::WindowActive | Qt::WindowFullScreen);
    // 确保关闭时自动删除
    setAttribute(Qt::WA_DeleteOnClose);

    // 获取主屏幕
    QScreen *screen = QApplication::primaryScreen();
    // 抓取整个屏幕内容
    m_loadPixmap = screen->grabWindow(QApplication::desktop()->winId());
    // 设置屏幕宽度、高度
    m_screenWidth = m_loadPixmap.width();
    m_screenHeight = m_loadPixmap.height();
}

第二个函数,重写相关事件处理函数,有关鼠标、键盘、以及绘图的事件函数,代码如下。

void PrintScreen::mousePressEvent(QMouseEvent *event)
{
    // 按下右键 显示菜单
    if (event->button() == Qt::RightButton)
        menu->exec(cursor().pos());  //菜单显示的位置跟随鼠标
    // 按下左键
    else if (event->button() == Qt::LeftButton){
        if (m_captureComplete && QRect(m_beginPoint, m_endPoint).contains(event->pos()))
        {
            m_isDragging = true;                          // 开始拖动
            m_dragPosition = event->pos() - m_beginPoint; // 计算开始拖动位置
        }
        else{
            m_isMousePress = true;       // 鼠标被按下
            m_isDragging = false;
            m_beginPoint = event->pos(); // 记录开始点  获取点击的坐标
            //qInfo()<< m_beginPoint;
        }
    }
}

void PrintScreen::mouseMoveEvent(QMouseEvent *event)
{
    // 获取屏幕尺寸
    QRect screenRect = QGuiApplication::primaryScreen()->geometry();
    // 鼠标按下且截图未完成
    if (m_isMousePress && !m_captureComplete){
        // 确保终点坐标不超过屏幕范围
        int x = qBound(screenRect.left(), event->pos().x(), screenRect.right());
        int y = qBound(screenRect.top(), event->pos().y(), screenRect.bottom());
        m_endPoint = QPoint(x, y);
    }
    // 正在拖动
    else if (m_isDragging){
        QPoint newTopLeft = event->pos() - m_dragPosition;
        // 确保新的顶点坐标不超过屏幕范围
        int x = qBound(screenRect.left(), newTopLeft.x(), screenRect.right() - m_dragPosition.x());
        int y = qBound(screenRect.top(), newTopLeft.y(), screenRect.bottom() - m_dragPosition.y());
        newTopLeft = QPoint(x, y);

        QPoint offset = newTopLeft - m_beginPoint;
        m_beginPoint += offset;
        m_endPoint += offset;
    }
    update();
    return QWidget::mouseMoveEvent(event);
}

void PrintScreen::mouseReleaseEvent(QMouseEvent *event)
{
    // 鼠标释放且截图未完成
    if (m_isMousePress && !m_captureComplete){
        m_endPoint = event->pos();  // 设置结束点
        m_isMousePress = false;     // 重置鼠标按下状态
        m_captureComplete = true;   // 标记截图完成
        update();
    }
    // 释放时正在拖动
    else if (m_isDragging){
        m_isDragging = false;
    }
    update();
}
// 键盘按下事件
void PrintScreen::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) // 按下回车键
    {
        // 保存图片
        QString filePath = QFileDialog::getSaveFileName(nullptr, "保存图片",QString(),"Images (*.png *.jpg)");
        if(!filePath.isEmpty()) {
            m_capturePixmap.save(filePath); // 保存截图到文件
        }
        //this->close(); //没必要退出
    }
    else if(event->key() == Qt::Key_Escape) // 按下Esc键
        this->close();
    else
        QWidget::keyPressEvent(event);
}

void PrintScreen::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)
    m_painter.begin(this);                                        // 开始绘制
    QColor shadowColor(0, 0, 0, 100);                             // 半透明遮罩颜色
    m_painter.setPen(QPen(Qt::blue, 1, Qt::SolidLine, Qt::FlatCap)); // 设置画笔
    m_painter.drawPixmap(0, 0, m_loadPixmap);                     // 绘制加载的屏幕截图
    m_painter.fillRect(m_loadPixmap.rect(), shadowColor);         // 绘制半透明遮罩
    QRect selectedRect = GetRect(m_beginPoint, m_endPoint);       // 获取选择区域
    m_capturePixmap = m_loadPixmap.copy(selectedRect);            // 截取选择区域的屏幕截图
    m_painter.drawPixmap(selectedRect.topLeft(), m_capturePixmap);// 绘制截取的区域
    m_painter.drawRect(selectedRect);                             // 绘制选择区域的边框
    m_painter.end();                                              // 结束绘制
}

第三个函数,创建菜单,以及菜单中子功能函数,代码如下。

void PrintScreen::CreateMenu(void)
{
    menu = new QMenu(this);//创建右键菜单
    menu->addAction("复制到粘贴板", this, [=](){copytoPasteboard(true);});
    menu->addAction("保存到图片", this, [=](){savetoImage();});
    menu->addAction("复制到文档", this, [=](){copytoPDF();});
    menu->addAction("文档打印", this, [=](){printtoPDF();});
    menu->addAction("退出截图", this, [=](){
        this->close();
    });
    menu->setStyleSheet("background-color: rgb(30, 30, 30, 100);color: rgb(255, 255, 255);"
                        "border-right:2px solid #aaaaaa; "
                        "border-bottom:2px solid #aaaaaa;"
                        "border-left:2px solid #aaaaaa;"
                        "border-top:2px solid #aaaaaa; "
                        "border-radius:5px;"
                        "font: 16pt ""黑体"";"
                        "selection-background-color: rgb(100, 40, 40);");
}

第四个函数,菜单中的按钮功能,第一个实现截图复制,代码如下。

//将截图复制到粘贴板
QPixmap PrintScreen::copytoPasteboard(bool hideflag)
{
   QPixmap pixmap;
   //截屏
   this->setWindowOpacity(0);//设置窗口透明度
   // 抓取整个屏幕内容
   QScreen *mainscreen = QApplication::primaryScreen();
   // 计算截屏区域位置及大小
   int x = std::min(m_beginPoint.x(), m_endPoint.x());
   int y = std::min(m_beginPoint.y(), m_endPoint.y());
   int width = std::abs(m_beginPoint.x() - m_endPoint.x());
   int height = std::abs(m_beginPoint.y() - m_endPoint.y());
   pixmap = mainscreen->grabWindow(QApplication::desktop()->winId(),x,y,width,height);
   this->setWindowOpacity(0.4);//设置窗口透明度
  //保存到粘贴板
   QClipboard *pic=QApplication::clipboard();
   pic->setPixmap(pixmap);
   if(hideflag)
       this->close();
   update();
   return pixmap;
}

第五个函数,菜单中的按钮功能,第一个实现截图保存为图片,代码如下。

//截图另存为图片
void PrintScreen::savetoImage(void)
{
    QString savename = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)+"/截图.png"; //默认路径:桌面 默认格式:png
    QString fileName = QFileDialog::getSaveFileName(this,"截图另存为",savename,"PNG (*.png);;BMP (*.bmp);;JPEG (*.jpg *.jpeg)");
    QPixmap pixmap = copytoPasteboard(true);  // 将截图复制到粘贴板
    if (!fileName.isEmpty()){
        pixmap.save(fileName);
    }
    pixmap.save(fileName);
    this->hide();
}

第六个函数,菜单中的按钮功能,第二个实现截图保存为文档,代码如下。

//截图另存为文档
#include <QTextDocument>
void PrintScreen::copytoPDF(void)
{
    pixmaps.append(copytoPasteboard(true));   // 将截图复制到粘贴板
}

第七个函数,菜单中的按钮功能,第三个实现文档打印,代码如下。

//将制到文档的截图打印出来
void PrintScreen::printtoPDF(void)
{
    pixmaps.append(copytoPasteboard(false));  // 将截图复制到粘贴板
    QString fileName = QFileDialog::getSaveFileName(this, "保存文档...", qApp->applicationDirPath()+"/savefile/", "*.pdf");
    if (!fileName.isEmpty())
    {
      QPrinter printer;
      printer.setOutputFormat(QPrinter::PdfFormat);
      printer.setOutputFileName(fileName);
      // 创建一个QPainter对象,用于在QPrinter上绘制
      QPainter painter(&printer);
      for (int i = 0; i < pixmaps.size(); ++i) {
          // 对于后续的图片,这是必要的;但对于第一张,如果QPrinter是新的,则可能不需要(但加上也无妨)
          if(i)
              printer.newPage();
          // 设置绘制区域,通常是从0,0到QPrinter的可打印区域
          QRect printableRect = printer.pageRect();
          // 缩放图片以适应打印区域
          int w = pixmaps[i].width();
          int h = pixmaps[i].height();
          pixmaps[i] = pixmaps[i].scaled(w,h, Qt::KeepAspectRatio, Qt::SmoothTransformation);
          // 计算绘制图片的起始点,使其居中
          QPoint pixmapPosition((printableRect.width() - w) / 2, (printableRect.height() - h) / 2);
          // 绘制图片
          painter.drawPixmap(pixmapPosition, pixmaps[i]);
      }
      // 结束绘制
      painter.end();
      pixmaps.clear();
    }
    this->close();
}

第八个函数,相关的绘图和获取尺寸功能,代码如下。

//绘制
void PrintScreen::saveImage(void)
{
    QScreen *screen = QApplication::primaryScreen();
    QPixmap pix = screen->grabWindow(0, m_beginPoint.rx(), m_beginPoint.ry(), m_screenWidth, m_screenHeight);
    QImage image = pix.toImage().convertToFormat(QImage::Format_RGBA8888);
}
QRect PrintScreen::GetRect(const QPoint &beginPoint, const QPoint &endPoint)
{
    int x = std::min(beginPoint.x(), endPoint.x());
    int y = std::min(beginPoint.y(), endPoint.y());
    int width = std::abs(beginPoint.x() - endPoint.x());
    int height = std::abs(beginPoint.y() - endPoint.y());
    if (width == 0) width = 1;   // 确保宽度至少为1像素
    if (height == 0) height = 1; // 确保高度至少为1像素
    return QRect(x, y, width, height);
}

自此,该类实现的相关功能函数已编写完毕,下面实现该截图功能被调用。

3.使用类

打开UI设计界面,在界面上添加截图按钮,如下所示。

编写该按钮功能,代码如下。

void MainWindow::on_pushButton_clicked()
{
    mprintScree = new PrintScreen();
    mprintScree->show();
}

编写完后,编译运行软件,显示界面如下。

点击截图功能,截图后,右键创建菜单,可将相应截图复制、保存为图片、或打印到PDF中,具体演示如下。


总结

博文中相应的工程代码Qt-Case.zip 利用Qt开发软件进行编的例程,为博文提供案例-CSDN文库

标签:beginPoint,截图,Qt,void,PrintScreen,PDF,event
From: https://blog.csdn.net/weixin_47006346/article/details/144415717

相关文章

  • QT使用promoted后样式(setStyleSheet)不生效
    1.理解promoted(提升)在Qt中的概念在QtDesigner中,“提升(Promoted)”是一种机制,它允许你使用自定义的部件类来替代标准的Qt部件类。这在你已经创建了一个从标准Qt部件(如QListWidget)派生的自定义部件(如ListMenu)并且希望在设计器环境中使用它时非常有用。2.样式不生效的......
  • 2024年DIIRC大模型行业应用十大典范案例集(附完整PDF下载)
    本案例集汇集当前大模型技术在各行各业中应用的杰出案例集,旨在展示大模型技术如何推动产业智能化、优化业务流程,并增强用户体验。案例集中的每一个案例都是基于实际应用,涵盖了从数字员工平台、智能写作工具、数据分析诊断系统,到知识管理平台和产业顾问等多个领域,体现了大模......
  • Qt/C++地图测距/显示不同线段的距离/拿到测距结果/测距结束信号
    一、前言说明地图测距在地图组件中属于一个比较小众的功能,但是又不得不提供,有时候用户希望直接在地图上选点,测算距离,尤其是在一些军事领域用的比较多,测距功能提炼出来的共性就是,每一段都有距离,最后鼠标右键或者双击结束测距,然后发个信号传过来总的距离。一般地图厂家也都提供了对......
  • Qt事件系统
    一、Qt事件简介:1、事件是对应用程序内部或者外部产生的事情或者动作的通称。2、Qt程序是事件驱动的,Qt事件的产生和处理是程序运行的主线,存在于程序的整个生命周期。3、Qt事件被封装为对象,所有的Qt事件均继承自抽象类QEvent。4、常见的事件如下:(1)键盘事件:QKeyEv......
  • NLP界大牛讲Transformer自然语言处理的经典书!,466页pdf及代码
    《Transformer自然语言处理实战》本书涵盖了Transformer在NLP领域的主要应用。内容介绍:首先介绍Transformer模型和HuggingFace生态系统。然后重点介绍情感分析任务以及TrainerAPI、Transformer的架构,并讲述了在多语言中识别文本内实体的任务,以及Transformer模型生成......
  • 网安大佬(黑客)整理的282G自学资料,高清视频,边学边练,高清PDF开放下载,零基础自学转行,首选
    前言在考虑成为黑客的步骤或学习曲线之前,先问自己一个问题,为什么要黑客?相信我,这个问题的答案肯定会告诉你一些方法。这个问题的可能答案是:只是感兴趣测试系统作为黑客工作那么我们首先要知道无论学习什么,基础知识一定要扎实,基础功非常的重要,找到一个合适的学习方法......
  • 如何在页面打开PDF文件?
    在前端开发中,有多种方式可以在页面上打开PDF文件。以下是一些常见的方法:使用<a>标签直接下载或打开PDF如果你的PDF文件是公开可访问的,并且你希望用户能够直接下载或打开它,你可以使用一个简单的<a>标签,并将其href属性设置为PDF文件的URL。例如:<ahref="path/to/your/file.pdf"......
  • 国产麒麟操作系统适配Qt?
    国产麒麟操作系统适配Qt?https://mp.weixin.qq.com/s/k9SYVl_pdAOmosXgBDv-jA原创 Qt历险记 Qt历险记  2024年11月09日09:09 贵州麒麟操作系统是支持Qt的,简单安装步骤 1. 更新系统软件源:打开终端并运行以下命令来更新软件包:sudoaptupdatesudoaptupgrade......
  • Qt类型转换合集
    QString转化为wchar_t*类型方法1分配内存voidmesServiceClient::allocate(wchar_t*&target,constQString&value){if(value==nullptr){target=nullptr;return;}QStringtemp=value;size_ttempLength=temp.size()+1;t......
  • Qt之热键盘使用(八)
    Qt开发 系列文章-Hot-keyboard(八)目录前言一、键盘使用二、QKeyEvent按键事件1.使用QShortcut类2.重写keyPressEvent三、QxtGlobalShortcut库四、QHotkey库总结前言Qt实现热键盘/快捷键的使用,比较直接简单的是利用Qt自带的QShortcut类、QKeyEvent类,通过改写相关......