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

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

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 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

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设计界面,在界面上添加截图按钮,如下所示。

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

c

复制代码

void MainWindow::on_pushButton_clicked()

{

mprintScree = new PrintScreen();

mprintScree->show();

}

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

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

总结

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

相关文章