如何在Qt中打印一个QWidget?

4

我需要知道如何将一个QWidget打印成PDF文件。这个Widget(QDialog)包含很多标签,一些QPlainTextEdit和一个背景图片。该对话框显示了一个已填写所有字段的收据。

我已经尝试使用QTextDocument和html来实现此目的,但是收据的复杂性(大量图像和格式自定义)使得html输出完全混乱。

这是文档。

收据图片


1
你可以展示一个关于你的小部件的最小、完整和可验证的示例 - eyllanesc
我尝试了QWidget::render()的解决方案,但是没有起作用,显示了以下错误:“QPainter::begin: Paint device returned engine == 0, type: 2” “QWidget::render: Cannot render with an inactive painter” - Alexey Smirnov
回答已编辑,不小心按下了回车键。 - Alexey Smirnov
请编辑您的问题并展示您已经尝试过哪些方法,即使这些方法没有奏效。同时,请提供一个能够重现您问题的最小化、完整化和可复现化的代码示例(MVCE)。 - eyllanesc
我使用了与QWidget::render()中解释的相同方法。 - Alexey Smirnov
显示剩余2条评论
2个回答

7

您需要使用 QPrinter,这是必须使用的对象,需要 QPainterQPrinter 中绘制小部件。

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QDialog w;

    w.setLayout(new QVBoxLayout());
    w.layout()->addWidget(new QLineEdit("text"));
    w.layout()->addWidget(new QPushButton("btn"));
    w.layout()->addWidget(new QPlainTextEdit("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris rutrum magna semper nisi faucibus, at auctor dolor ullamcorper. Phasellus facilisis blandit augue sit amet placerat. Aliquam nec imperdiet diam. Proin dignissim vulputate metus, nec tincidunt magna vulputate ac. Praesent vel felis ac dolor viverra tempus eu vitae neque. Nulla efficitur gravida arcu id suscipit. Maecenas placerat egestas velit quis interdum. Nulla diam massa, hendrerit vitae mi et, placerat aliquam nisl. Donec tincidunt lobortis orci, quis egestas augue tempus sed. Nulla vel dolor eget ipsum accumsan placerat ut at magna."));
    w.show();

    QPushButton btn("print");
    btn.show();

    QObject::connect(&btn, &QPushButton::clicked, [&w](){
        QPrinter printer(QPrinter::HighResolution);
        printer.setOutputFormat(QPrinter::PdfFormat);
        printer.setOutputFileName("output.pdf");
        printer.setPageMargins(12, 16, 12, 20, QPrinter::Millimeter);
        printer.setFullPage(false);

        QPainter painter(&printer);

        double xscale = printer.pageRect().width() / double(w.width());
        double yscale = printer.pageRect().height() / double(w.height());
        double scale = qMin(xscale, yscale);
        painter.translate(printer.paperRect().center());
        painter.scale(scale, scale);
        painter.translate(-w.width()/ 2, -w.height()/ 2);
        w.render(&painter);
    });

    return a.exec();
}

Widget:

enter image description here

output.pdf

enter image description here


这个完美地解决了问题,非常感谢。我几乎确定我也尝试过这个方法,但由于某些原因它没有起作用,可能是我写错了一些参数。答案已被标记为已接受。 - Alexey Smirnov
@AlexeySmirnov请将您错误放置的参数放置在此处,但是由于他们会认为这是重复的问题,因此此问题已关闭。 - eyllanesc

0
Eyllanesc的解决方案完美运行,但是我在pageRect()paperRect()函数上收到了警告。这些函数似乎已经过时。 以下是去除了废弃函数的代码的前后对比。
//-------------------------- Code BEFORE --------------------------//
double xscale = printer.pageRect().width() / double(w.width());
double yscale = printer.pageRect().height() / double(w.height());
double scale = qMin(xscale, yscale);
painter.translate(printer.paperRect().center());
painter.scale(scale, scale);
painter.translate(-w.width()/ 2, -w.height()/ 2);
w.render(&painter);
//-----------------------------------------------------------------//

//-------------------------- Code AFTER ---------------------------//
double pageRectWidth  = printer.pageLayout().pageSize().sizePixels(96).width()-printer.pageLayout().marginsPixels(96).left()-printer.pageLayout().marginsPixels(96).right();
double pageRectHeight = printer.pageLayout().pageSize().sizePixels(96).height()-printer.pageLayout().marginsPixels(96).top()-printer.pageLayout().marginsPixels(96).bottom();

double xscale = pageRectWidth / double(w.width());
double yscale = pageRectHeight / double(w.height());
double scale = qMin(xscale, yscale);
painter.translate(QPoint(printer.pageLayout().pageSize().sizePixels(96).width()/2,printer.pageLayout().pageSize().sizePixels(96).height()/2));
painter.scale(scale, scale);
painter.translate(-w.width()/ 2, -w.height()/ 2);
w.render(&painter);
//-----------------------------------------------------------------//

我在sizePixels()函数中使用了96,因为这是默认分辨率。
希望这段代码能够帮到你 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接