- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试在 Windows 下使用 Qt5 生成 pdf。我的文档包含文本、图像和图表。由于我熟悉 Qt 和 Qwt,我认为最好的策略是使用我的文档布局创建一个 QWidget
并简单地打印它。但我遇到了问题,无法得到可接受的结果。
这是我的 MCVE,一个简单的页面文档:
基于 Qt document和 How can I print a QWidget in Qt? ,我最终得到了这段代码:
main.cpp:
#include <QApplication>
#include <QIcon>
#include <QDesktopServices>
#include <QWidget>
#include <QPrinter>
#include <QPainter>
#include <QPagedPaintDevice>
#include <QUrl>
#include "ui_report.h"
#include "qwt_plot.h"
#include "qwt_plot_curve.h"
#include "qwt_plot_canvas.h"
#include "qwt_point_data.h"
#include "qwt_legend.h"
#include <sstream>
#include <memory>
bool printWidget( QWidget& widget, bool highResolution, const std::string& fileName )
{
QPrinter printer( highResolution ? QPrinter::HighResolution : QPrinter::ScreenResolution );
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOrientation(QPrinter::Portrait);
printer.setPaperSize(QPrinter::A4);
printer.setPageMargins(15,15,15,15,QPrinter::Millimeter);
printer.setFullPage(true);
printer.setOutputFileName(fromSDEString(fileName.c_str()));
QPainter painter(&printer);
double xscale = printer.pageRect().width()/double(widget.width());
double yscale = printer.pageRect().height()/double(widget.height());
double scale = qMin(xscale, yscale);
painter.translate(printer.paperRect().x() + printer.pageRect().width()/2,
printer.paperRect().y() + printer.pageRect().height()/2);
painter.scale(scale, scale);
painter.translate(-widget.width()/2, -widget.height()/2);
widget.render(&painter, QPoint(), QRegion(), QWidget::DrawChildren);
return painter.end();
}
bool generateReport( bool drawWithPrinterResolution, bool printHighResolution, const std::string& fileName )
{
QWidget widget;
Ui::Report ui;
ui.setupUi( &widget );
if ( drawWithPrinterResolution )
{
QPrinter printer( printHighResolution ? QPrinter::HighResolution : QPrinter::ScreenResolution );
printer.setOrientation(QPrinter::Portrait);
printer.setPaperSize(QPrinter::A4);
printer.setPageMargins(15,15,15,15,QPrinter::Millimeter);
printer.setFullPage(true);
// force printer page size to be used:
QSize pageSize = printer.pageRect().size();
widget.resize( pageSize );
}
ui.header->setFrameShape( QFrame::Shape::Box );
QHBoxLayout* headerLayout = new QHBoxLayout(ui.header);
QLabel* icon = new QLabel(ui.header);
QSize size = ui.header->size();
icon->setPixmap( QPixmap( ":/gui_test/mainframe.png" ).scaledToHeight( size.height() ) );
headerLayout->addWidget( icon );
headerLayout->addWidget( new QLabel("Document title",ui.header) );
headerLayout->setStretch( 0, 0 );
headerLayout->setStretch( 1, 1 );
ui.inputs->setText( "<b>Info</b>: Information" );
QwtPlot* plot = new QwtPlot( &widget );
QwtPlotCurve* curve = new QwtPlotCurve("Plots");
curve->setStyle( QwtPlotCurve::Lines );
QVector<QPointF> samples;
for ( size_t i = 0; i != 100; ++i )
{
samples.push_back(QPointF(i,20*i+10));
}
curve->setData(new QwtPointSeriesData(samples));
curve->attach(plot);
plot->setTitle( "Result" );
plot->setAxisScale( QwtPlot::xBottom, samples.front().rx(), samples.back().rx() );
plot->replot();
ui.graphLayout->addWidget( plot );
if ( printWidget( widget, printHighResolution, fileName ) )
{
QDesktopServices::openUrl(QUrl::fromLocalFile(fileName.c_str()));
return true;
}
else
{
return false;
}
}
int main( int argc, char* argv[] )
{
QApplication app( argc, argv );
app.setWindowIcon( QIcon( ":/gui_test/mainframe.png" ) );
generateReport( false, false, "report_small_widget_to_screen.pdf" );
generateReport( false, true, "report_small_widget_to_high.pdf" );
generateReport( true, false, "report_big_widget_to_screen.pdf" );
generateReport( true, true, "report_big_widget_to_high.pdf" );
return 0;
}
报告.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Report</class>
<widget class="QWidget" name="Report">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>525</width>
<height>742</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,100,0">
<item>
<widget class="QFrame" name="header"/>
</item>
<item>
<widget class="QLabel" name="inputs">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="graphLayout"/>
</item>
<item>
<widget class="QWidget" name="footer" native="true"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
mainframe.png:一个 256x256 像素的 Qt 图标:http://icons.iconarchive.com/icons/alecive/flatwoken/256/Apps-Qt-icon.png .
如您所见,这会生成 4 个文件:
QPrinter::ScreenResolution
QPrinter::HighResolution
QPrinter::ScreenResolution
打印QPrinter::HighResolution
打印没有给我一个可接受的结果:
我应该更改什么以获得良好的输出?
report_small_widget_to_screen.pdf 看起来像(一切都是像素化的):
report_small_widget_to_high.pdf 看起来像(只有文本没有像素化):
report_big_widget_to_high.pdf 看起来像(一切都太小了):
注意:我只是使用更大的 .ui 资源 (2100x2970) 运行相同的测试,然后图像分辨率看起来更好,但文本显得非常小。我想知道 QWidget 打印是这里合适的解决方案,因为它看起来像文本大小取决于 ui 大小,所以你无法控制文本的大小(就像你在像 Word 这样的文档中处理字体大小...... )
最佳答案
就我个人而言,我会强烈考虑将内容创建为 QTextDocument然后打印它。您可以(IIRC,有一段时间没有使用 QwtPlot)将图表渲染为图像。然后很容易add the image到文档中任何你想要的地方。当然,与您的静态图像相同。您可以在文档中使用 HTML/CSS(尽管类名中有“Text”),以及许多其他选项。
根据要求添加示例:
这将非常简化并且没有完全形成,但希望它能帮助...
QTextDocument qtdoc; // start with a QTextDocument
// prepare standard html with embedded image
QString html = "<html><body>" \
"<h1>Hello World!</h1>" \
"<img src='mydata://myimg.png' border='0' />" \
"</body></html>";
QImage image = getChartImage(); // theoretical function
// here we add the actual image data to the document
qtdoc.addResource(QTextDocument::ImageResource, QUrl("mydata://myimg.png"), image);
qtdoc.setHtml(html);
// document is now fully formed and ready for display/print
要打印成 PDF 或 HTML 文件:
void printToFile(const QTextDocument & qtdoc)
{
QString fn = QFileDialog::getSaveFileName(this, tr("Select output file"), QString(), tr("PDF Files(*.pdf);;HTML-Files (*.htm *.html)"));
if (fn.isEmpty())
return;
if (fn.endsWith(".pdf", Qt::CaseInsensitive)) {
QPrinter printer;
printer.setPageMargins(10.0,10.0,10.0,10.0,printer.Millimeter);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setColorMode(QPrinter::Color);
printer.setOutputFileName(fn);
qtdoc.print(&printer);
}
else { // HTML
QTextDocumentWriter writer(fn);
writer.write(qtdoc);
}
}
输出到打印机:
void print(const QTextDocument & qtdoc)
{
QPrinter printer;
printer.setPageMargins(10.0,10.0,10.0,10.0,printer.Millimeter);
QPrintDialog *dialog = new QPrintDialog(&printer, this);
dialog->setWindowTitle(tr("Print Document"));
if (dialog->exec() != QDialog::Accepted)
return;
qtdoc.print(&printer);
}
工作版本的实际屏幕截图(它的代码以 here 开头,但遵循起来有点繁琐):
关于c++ - 无法使用 Qt 生成具有可接受输出质量的 pdf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47870408/
我正在使用 OUTFILE 命令,但由于权限问题和安全风险,我想将 shell 的输出转储到文件中,但出现了一些错误。我试过的 #This is a simple shell to connect t
我刚刚开始学习 Java,我想克服在尝试为这个“问题”创建 Java 程序时出现的障碍。这是我必须创建一个程序来解决的问题: Tandy 喜欢分发糖果,但只有 n 颗糖果。对于她给第 i 个糖果的人,
你好,我想知道我是否可以得到一些帮助来解决我在 C++ 中打印出 vector 内容的问题 我试图以特定顺序在一个或两个函数调用中输出一个类的所有变量。但是我在遍历 vector 时收到一个奇怪的错误
我正在将 intellij (2019.1.1) 用于 java gradle (5.4.1) 项目,并使用 lombok (1.18.6) 来自动生成代码。 Intellij 将生成的源放在 out
编辑:在与 guest271314 交流后,我意识到问题的措辞(在我的问题正文中)可能具有误导性。我保留了旧版本并更好地改写了新版本 背景: 从远程服务器获取 JSON 时,响应 header 包含一
我的问题可能有点令人困惑。我遇到的问题是我正在使用来自 Java 的 StoredProcedureCall 调用过程,例如: StoredProcedureCall call = new Store
在我使用的一些IDL中,我注意到在方法中标记返回值有2个约定-[in, out]和[out, retval]。 当存在多个返回值时,似乎使用了[in, out],例如: HRESULT MyMetho
当我查看 gar -h 的帮助输出时,它告诉我: [...] gar: supported targets: elf64-x86-64 elf32-i386 a.out-i386-linux [...
我想循环遍历一个列表,并以 HTML 格式打印其中的一部分,以代码格式打印其中的一部分。所以更准确地说:我想产生与这相同的输出 1 is a great number 2 is a great
我有下面的tekton管道,并尝试在Google Cloud上运行。集群角色绑定。集群角色。该服务帐户具有以下权限。。例外。不确定需要为服务帐户设置什么权限。
当尝试从 make 过滤非常长的输出以获取特定警告或错误消息时,第一个想法是这样的: $ make | grep -i 'warning: someone set up us the bomb' 然而
我正在创建一个抽象工具类,该类对另一组外部类(不受我控制)进行操作。外部类在某些接口(interface)点概念上相似,但访问它们相似属性的语法不同。它们还具有不同的语法来应用工具操作的结果。我创建了
这个问题已经有答案了: What do numbers starting with 0 mean in python? (9 个回答) 已关闭 7 年前。 在我的代码中使用按位与运算符 (&) 时,我
我写了这段代码来解析输入文件中的行输入格式:电影 ID 可以有多个条目,所以我们应该计算平均值输出:**没有重复(这是问题所在) import re f = open("ratings2.txt",
我需要处理超过 1000 万个光谱数据集。数据结构如下:大约有 1000 个 .fits(.fits 是某种数据存储格式)文件,每个文件包含大约 600-1000 个光谱,其中每个光谱中有大约 450
我编写了一个简单的 C 程序,它读取一个文件并生成一个包含每个单词及其出现频率的表格。 该程序有效,我已经能够在 Linux 上运行的终端中获得显示的输出,但是,我不确定如何获得生成的显示以生成包含词
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
1.普通的输出: print(str)#str是任意一个字符串,数字··· 2.格式化输出: ?
我无法让 logstash 正常工作。 Basic logstash Example作品。但后来我与 Advanced Pipeline Example 作斗争.也许这也可能是 Elasticsear
这是我想要做的: 我想让用户给我的程序一些声音数据(通过麦克风输入),然后保持 250 毫秒,然后通过扬声器输出。 我已经使用 Java Sound API 做到了这一点。问题是它有点慢。从发出声音到
我是一名优秀的程序员,十分优秀!