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

server/2024/12/14 18:43:27/

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();elseQWidget::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"; //默认路径:桌面 默认格式:pngQString 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文库。


http://www.ppmy.cn/server/150158.html

相关文章

Ubuntu中iptables默认是开启的吗

不&#xff0c;Ubuntu 中 iptables 默认不是开启的。 虽然 Ubuntu 系统默认安装了 iptables 软件包&#xff08;你可以通过 dpkg -l iptables 或 which iptables 命令来验证&#xff09;&#xff0c;但这并不意味着 iptables 规则已经生效。实际上&#xff0c;iptables 的规则…

《从零开始:轻松入门数据结构的世界》

一、为什么数据结构如此重要&#xff1f; 数据结构就像是程序的骨架&#xff0c;它决定了数据在内存中的存储方式&#xff0c;以及我们如何对这些数据进行操作。一个好的数据结构可以大大提高程序的运行效率&#xff0c;减少内存消耗。我们将通过一个简单的比喻来理解这一点&a…

《Django 5 By Example》阅读笔记:p493-p520

《Django 5 By Example》学习第 17 天&#xff0c;p493-p520 总结&#xff0c;总计 28 页。 一、技术总结 1.internationalization(国际化) vs localization(本地化) (1)18n&#xff0c;L10n&#xff0c;g11n 以前总觉得这两个缩写好难记&#xff0c;今天仔细看了下维基百科…

OpenGL 几何着色器高级应用

几何着色器高级应用 概念回顾 几何着色器(Geometry Shader)是 OpenGL 管线中的可选着色器阶段,位于顶点着色器(Vertex Shader) 和光栅化阶段 之间。 其核心功能是基于输入的图元(如点、线或三角形),生成新的图元,或对输入的图元进行修改。 几何着色器的执行是以图元…

Apache Commons Utils 类库使用

Apache Commons Utils 是一组开源的 Java 工具类库&#xff0c;提供了许多在开发中常用且实用的功能&#xff0c;涵盖了字符串处理、集合操作、日期时间处理、文件操作等多个方面。下面是对 Apache Commons Utils 中一些主要工具类的详细介绍和使用示例。 1. Commons Lang (or…

C# 异常处理全解析:让程序告别崩溃噩梦

一、什么是异常&#xff1f; 异常是程序在运行过程中发生的错误或意外情况。当程序遇到无法正常执行的情形时&#xff0c;会抛出一个异常&#xff0c;以通知程序发生了错误。异常是程序中的一种事件&#xff0c;需要被捕获和处理&#xff0c;否则程序可能会崩溃或终止运行。 …

使用HashMap实现LRU

1. 使用LinkedList实现 import java.util.LinkedList;public class Main {public static void main(String[] args) throws Exception {cacheLRU cache new cacheLRU(3);cache.add(1);cache.add(2);cache.add(3);System.out.print(cache.get(1));System.out.print(cache.get(…

EXCEL 数据透视表基础操作

目录 1 选择数据&#xff0c;插入数据透视表 2 选择数据透视表生成位置 3 出现了数据透视表的面板 4 数据透视表的基本结构认识 4.1 交叉表/列联表 4.2 row, column, cell 一个新增的筛选器&#xff0c;就这么简单 4.3 可以只添加 rowcell/值 &#xff0c;也可以colu…