如何将 WT 小部件放入 PDF?

Posted

技术标签:

【中文标题】如何将 WT 小部件放入 PDF?【英文标题】:How to place WT widgets into PDF? 【发布时间】:2014-05-01 15:55:03 【问题描述】:

更新

我还在 WT 论坛http://redmine.webtoolkit.eu/issues/3042 上发布了关于此问题的帖子。对于那些正在寻找有关样式的更多信息的人,您可以在此处找到更多信息。

原帖

我在将 WGroupBox(最终是 WTable)放入 PDF 时遇到问题。我正在使用小部件库中的 PDF 示例代码,并且一直在尝试将我拥有的 WTable 放入 PDF 中,但不成功我将其调回 WGroupBox。 http://www.webtoolkit.eu/widgets/media/pdf-output “PDF 图像”示例工作正常。 “将 html 渲染为 PDF”是我遇到问题的地方。 我使用的示例与页面上显示的完全一样,唯一添加的是用于 PDF 中我想要的项目的 WContainerWidget 指针。

我不明白我需要将什么作为将传递给 WPdfRenderer 渲染函数的 WString 传递给 renderPdf 函数,我尝试检查小部件库代码的 html 以与我自己的进行比较,并模仿画廊正在做,但到目前为止一切都未能制作PDF。

这是我按下“创建 Pdf”按钮后 URL 的样子,它显示一个空白页面,左下方有一个空的 pdf“正在加载”消息。

http://127.0.0.1:8080/ui/report.pdf?wtd=Psx1WfLVpsvVDpxW&request=resource&resource=oylm6i6&rand=1

下面的示例代码。

//This is the code I have executing on my main page, just a group box with a few labels, a button for the sample pdf, a chart, and another button for the more advanced sample pdf(this one is broken).
//PDF Images sample/////////////////////////////////////////////////////////////////////////
Wt::WContainerWidget* container = table_container;
Wt::WResource* sample_pdf = new SamplePdfResource(container);
Wt::WPushButton* button1 = new Wt::WPushButton("Create pdf sample", container);
button1->setLink(sample_pdf);

//PDF Images sample chart///////////////////////////////////////////////////////////////////
Wt::Chart::WCartesianChart* chart = CreateCartesianChart(table_container);
Wt::WPainter* p = new Wt::WPainter((Wt::WPdfImage*)sample_pdf);
chart->paint(*p);
std::ofstream f("chart.pdf", std::ios::out | std::ios::binary);
sample_pdf->write(f);

//GroupBox to be placed into PDF////////////////////////////////////////////////////////////
Wt::WGroupBox* group_box = new Wt::WGroupBox("Example Group Box", table_container);
group_box->addStyleClass("example");
Wt::WText* text = new Wt::WText("This is a text sample within the group box 1", group_box);
text            = new Wt::WText("This is a text sample within the group box 2", group_box);
text            = new Wt::WText("This is a text sample within the group box 3", group_box);

//The pdf to take the GroupBox//////////////////////////////////////////////////////////////
Wt::WPushButton* button = new Wt::WPushButton("Create pdf", container);
Wt::WResource* pdf = new ReportResource(group_box, container);
button->setLink(pdf);

以下是小部件库中的“将 HTML 渲染为 PDF”代码,其中包含用于目标的新容器小部件。

namespace 
    void HPDF_STDCALL error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no,
               void *user_data) 
    fprintf(stderr, "libharu error: error_no=%04X, detail_no=%d\n",
        (unsigned int) error_no, (int) detail_no);
    


class ReportResource : public Wt::WResource

public:
  ReportResource(Wt::WContainerWidget* target, Wt::WObject* parent = 0)
    : Wt::WResource(parent),
    _target(NULL)
  
    suggestFileName("report.pdf");
    _target = target;
  

  virtual void handleRequest(const Wt::Http::Request& request, Wt::Http::Response& response)
  
    response.setMimeType("application/pdf");

    HPDF_Doc pdf = HPDF_New(error_handler, 0);

    // Note: UTF-8 encoding (for TrueType fonts) is only available since libharu 2.3.0 !
    HPDF_UseUTFEncodings(pdf);

    renderReport(pdf);

    HPDF_SaveToStream(pdf);
    unsigned int size = HPDF_GetStreamSize(pdf);
    HPDF_BYTE *buf = new HPDF_BYTE[size];
    HPDF_ReadFromStream (pdf, buf, &size);
    HPDF_Free(pdf);
    response.out().write((char*)buf, size);
    delete[] buf;
  

private:

  Wt::WContainerWidget* _target;

  void renderReport(HPDF_Doc pdf)
  
    std::stringstream ss;
    _target->htmlText(ss);
    std::string out = ss.str();
    std::string out_id = _target->id();
    std::string out_parent_id = _target->parent()->id();

    renderPdf(Wt::WString::tr(???), pdf);
  

  void renderPdf(const Wt::WString& html, HPDF_Doc pdf)
  
    HPDF_Page page = HPDF_AddPage(pdf);
    HPDF_Page_SetSize(page, HPDF_PAGE_SIZE_A4, HPDF_PAGE_PORTRAIT);

    Wt::Render::WPdfRenderer renderer(pdf, page);
    renderer.setMargin(2.54);
    renderer.setDpi(96);
    renderer.render(html);
  
;

//PDF 图片代码

class SamplePdfResource : public Wt::WPdfImage

public:
  SamplePdfResource(Wt::WObject *parent = 0)
    : Wt::WPdfImage(400, 300, parent)
  
    suggestFileName("line.pdf");
    paint();
  

private:
  void paint()
  
    Wt::WPainter painter(this);

    Wt::WPen thickPen;
    thickPen.setWidth(5);
    painter.setPen(thickPen);
    painter.drawLine(50, 250, 150, 50);
    painter.drawLine(150, 50, 250, 50);

    painter.drawText(0, 0, 400, 300, Wt::AlignCenter | Wt::AlignTop, "Hello, PDF");
  
;

//笛卡尔图初始化

Wt::Chart::WCartesianChart* CreateCartesianChart(Wt::WContainerWidget* parent)

Wt::WStandardItemModel *model = new Wt::WStandardItemModel(PERFORMANCE_HISTORY, 2, parent);

//Create the scatter plot.
Wt::Chart::WCartesianChart* chart = new Wt::Chart::WCartesianChart(parent);
//Give the chart an empty model to fill with data
chart->setModel(model);
//Set which column holds X data
chart->setXSeriesColumn(0);

//Get the axes
Wt::Chart::WAxis& x_axis  = chart->axis(Wt::Chart::Axis::XAxis);
Wt::Chart::WAxis& y1_axis = chart->axis(Wt::Chart::Axis::Y1Axis);
Wt::Chart::WAxis& y2_axis = chart->axis(Wt::Chart::Axis::Y2Axis);

//Modify axes attributes
x_axis.setRange(0, PERFORMANCE_HISTORY);
x_axis.setGridLinesEnabled(true);
x_axis.setLabelInterval(PERFORMANCE_HISTORY / 10);

y1_axis.setRange(0, 100);
y1_axis.setGridLinesEnabled(true);
y1_axis.setLabelInterval(10);

y2_axis.setRange(0, 100);
y2_axis.setVisible(true);
y2_axis.setLabelInterval(10);

//Set chart type
chart->setType(Wt::Chart::ChartType::ScatterPlot);

// Typically, for mathematical functions, you want the axes to cross at the 0 mark:
chart->axis(Wt::Chart::Axis::XAxis).setLocation(Wt::Chart::AxisValue::ZeroValue);
chart->axis(Wt::Chart::Axis::Y1Axis).setLocation(Wt::Chart::AxisValue::ZeroValue);
chart->axis(Wt::Chart::Axis::Y2Axis).setLocation(Wt::Chart::AxisValue::ZeroValue);

// Add the lines
Wt::Chart::WDataSeries s(1, Wt::Chart::SeriesType::LineSeries);
chart->addSeries(s);

//Size the display size of the chart, has no effect on scale
chart->resize(300, 300);

return chart;

【问题讨论】:

【参考方案1】:

pdf 渲染器采用 HTML 字符串。所以我认为解决方案是

renderPdf(WString::fromUTF8(out), pdf);

【讨论】:

很好,很有效。但是,pdf 的样式不像我的页面那样。我正在使用 boost 样式,组框有大字母和下面的一行,其下显示其子小部件。有没有办法将我页面上的内容镜像到 PDF 中?这就是上面在 PDF 中所做的代码:“示例组框这是组框内的文本示例 1这是组框内的文本示例 2这是组框内的文本示例 3”文本是背靠背的,据我所知,我那里没有任何 WBreaks。但是 Group 框没有样式,它只是取了文本。

以上是关于如何将 WT 小部件放入 PDF?的主要内容,如果未能解决你的问题,请参考以下文章

从其他网页调用 c++ web toolkit 小部件?

如何将小部件放入空的 QWidget 中? [关闭]

Magento:如何将小部件放入布局 xml?

Flutter:如何将图像(裁剪)放入下一个有状态/更少的小部件

如何将 QPushButton 放入小部件中的 Qt3DWindow 中?

如何在小部件的容器内显示 pdf [flutter-web]