最近做了一个和QT5有关的项目,遇到很多问题也学习到不少,特意写下来希望帮到更多的人。(我的版本VS2017+QT5.12.0)
一、QT5截图并保存到本地
在头文件添加必须项
#include <QScreen>
#include <QPixmap>
截图功能的代码
QScreen *screen=QGuiApplication::primaryScreen();
QPixmap pixmap=screen->grabWindow(ui->qvtkWidget->winId());
//qvtkWidget->winId()这是你要截图的控件的winID,主窗口0(全屏截图的意思)winId(0)
pixmap.save("E:/screen.jpg","jpg"); //保存地址可以改成你自己的
二、QT5输出PDF/WORD文档(类似于打印报表)
添加头文件
#include <QPrinter>
输出带有文字的PDF
QPainter text_painter;
QPrinter text_printer;
text_printer.setOutputFormat(QPrinter::PdfFormat);
text_printer.setOutputFileName("test_text.pdf");
text_painter.begin(&text_printer);
for (int i = 0; i < 5; i++)
text_painter.drawText(10, i * 30, "hello world");
text_painter.end();
输出带有图片的PDF
QPrinter printer_pixmap(QPrinter::HighResolution);
printer_pixmap.setPageSize(QPrinter::A4); //设置纸张大小为A4
printer_pixmap.setOutputFormat(QPrinter::PdfFormat); //设置输出格式为pdf
printer_pixmap.setOutputFileName(sFilePdf1); //设置输出路径
QPainter painter_pixmap;
//myImg是自定义的照片
QPixmap pixmap(myImg);
painter_pixmap.begin(&printer_pixmap);
QRect rect = painter_pixmap.viewport();
int multiple = rect.width()/pixmap.width();
painter_pixmap.scale(multiple, multiple); //将图像(所有要画的东西)在pdf上放大multiple-1倍
painter_pixmap.drawPixmap(0, 0, pixmap); //画图
painter_pixmap.end();
但我用这种方法始终无法生成带有图片的pdf文档,不知道哪里出了问题。就换了另一种方法,就可以生成文字图片都有的pdf文档。
核心思想就是以html语言为核心对pdf/word格式编写,再用QTextDocument输出。
头文件(我直接把我所有的都写出来了,你们可以根据自己的需求修改):
#include <QTextDocument>
#include <QtPrintSupport/QPrinter>
#include <QPainter>
#include <QPen>
#include <QTextBrowser>
#include <QPixmap>
#include <QDateTime>
#include <QDesktopWidget>
#include <QPdfWriter>
#include <QScreen>
#include <QFile>
#include <QTextBlock>
代码大致分为两部分:
第一部分:对文档格式编写(注意:格式可以根据自己需求改,书写格式遵循H5语言即可)
QString saveHtmlToPDF()
{
QString html = "";
html += "<html>";
html += "<head>";
html += "<title>qt生成pdf报表</title>";
html += "<head>";
html += "<body style=\"bgcolor:yellow\">";
html += "<h1 align=\"center\">xxx报表</h1>";
html += "<h2 align=\"left\">一.一级标题</h2>";
html += "<h3 align=\"left\">1.二级标题</h3>";
html += "<hr>";
QString text;
text = ui->textBrowser->document()->toHtml();
//这里是将qt的文本控件内容直接输入给pdf文档
html += text;
html += "<hr>";
html += "<h3 align=\"left\">2.图像数据</h3>";
html += "<p align=\"left\">(1)图像名称1</p>";
html += "<p align=\"center\"><img src=\"F:\\tabWidget_screen1.jpg\" alt=\"picture\" width=\"582\" height=\"400\"></p>";
html += "<p align=\"left\">(2)图像名称2</p>";
html += "<p align=\"center\"><img src=\"F:\\tabWidget_screen2.jpg\" alt=\"picture\" width=\"582\" height=\"400\"></p>";
html += "<p align=\"left\">(3)图像名称3</p>";
html += "<p align=\"center\"><img src=\"F:\\tabWidget_screen3.jpg\" alt=\"picture\" width=\"582\" height=\"400\"></p>";
html += "<h2 align=\"left\">二.缺陷检测</h2>";
html += "<h3 align=\"left\">1.总缺陷点云</h3>";
html += "<p align=\"left\">(1)数量信息</p>";
html += "<hr>"; //生成一条横线
text = ui->lineEdit->text(); //获取控件的文本内容
html += text;
//文档结尾可以加上生成时间,看你自己选择。若要加上功能头文件还需添加 #include <QDateTime>
html += "<p align=\"left\">报表生成时间:</p>";
QDateTime current_date_time = QDateTime::currentDateTime();
QString current_date = current_date_time.toString("yyyy-MM-dd hh:mm:ss");
html += current_date;
html += "</body>";
html += "</html>";
return html;
}
第二部分:将以上html转化成QT的文件输出文档
void picture2Pdf()
{
QPrinter printer_pixmap(QPrinter::HighResolution);
printer_pixmap.setPageSize(QPrinter::A4); //设置纸张大小为A4
printer_pixmap.setOutputFormat(QPrinter::PdfFormat); //设置输出格式为pdf
QString file_path = QFileDialog::getSaveFileName(this, "保存报表", QString(), "*.pdf"); //用文件对话框设置输出路径
if (!file_path.isEmpty())
{
//如果没有写后缀就自动加上
if (QFileInfo(file_path).suffix().isEmpty())
{
file_path.append(".pdf"); //或者 file_path+=".pdf"
}
}
//若你pdf文档里插入的图片是截图qt界面,这部分代码则需要。若你pdf文档要插入的图片是本地自带的,则不需要这部分截图代码
QScreen *screenNew = QGuiApplication::primaryScreen();
QPixmap pixmapNew = screenNew->grabWindow(ui->qvtkWidget_2->winId());
pixmap.save("E:/screen.jpg","jpg");
//截图代码完毕,若你需要多次截图,更换grabWindow(ui->qvtkWidget_2->winId())中的内容即可
QTextDocument document;
QString html = saveHtmlToPDF();
document.setHtml(html);
document.print(&printer_pixmap);
document.end();
}
若要生成word文档,只需要将第二部分函数中的
QTextDocument document;
QString html = saveHtmlToPDF();
document.setHtml(html);
document.print(&printer_pixmap);
document.end();
更换为
QString docname = "E:/testhtmlword.doc"; //文件保存地址也可更改为自定义位置,参考我上面的代码
QString html = saveHtmlToWord(); //pdf中的函数名是saveHtmlToPDF()
QFile outFile(docname);
outFile.open(QIODevice::WriteOnly | QIODevice::Append );
QTextStream ts(&outFile);
ts<<html<<endl;
三、QT5输出PDF/WORD文档容易出现的问题
问题1:error LNK2019: 无法解析的外部符号 “_declspec(dllimport) public: __thiscall QPrintDialog::QPrintDialog(class QPrinter *,class QWidget *)” (__imp??0QPrintDialog@@QAE@PAVQPrinter@@PAVQWidget@@@Z),该符号在函数 “protected: void __thiscall EasyEditor::showPrintText(void)” (?showPrintText@EasyEditor@@IAEXXZ) 中被引用 F:\QtSourceCode\Easy Editor\Easy Editor\EasyEditor.objEasy Editor
解决方式:右击项目,选择“属性”–>“链接器”–>“输入”–>”附加依赖项”–>”编辑”
在最后添加上“Qt5PrintSupport.lib”即可。
问题2:使用QPrinter和QprintDialog类时的附加处理
解决方式:①若是在QT Creator中,需要在 (.pro)工程文件中加入 “QT+= printsupport ”,否则会编译报错
②若是在VS环境下,只需在相应头文件中添加以下两条语句(我上文分开提到过,这里集中说一下)
#include <QtPrintSupport/QPrintDialog>
#include <QtPrintSupport/QPrinter>
四、QT5中文乱码
1.QT5软件界面中文乱码(改变编码格式为utf-8,在cpp文件中设置编码字符集,只在VS编译器下生效)
解决:
#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif
2.QString中文乱码
解决:
QString str = QString::fromUtf8("中文"); // 源码是UTF-8 编码
QString str = QString::fromLocal8Bit("中文"); // 源码是GBK 编码(记事本中的 ANSI 编码)
这样两种方法也可以解决QT5输出的PDF/WORD中文乱码问题,总结一句中文乱码就是编码格式问题。