Render QGraphicsScene to a QPrinter to export PDF



  • Hi there,

    Can anyone tell me why this works:

    @
    void Partitura::print()
    {
    QPrinter printer(QPrinter::HighResolution);
    printer.setPageSize(QPrinter::A4);
    printer.setOrientation(QPrinter::Portrait);
    QPrintDialog dlg(&printer);
    if(dlg.exec()==QDialog::Accepted) {
    QPainter p(&printer);
    scene->render(&p);
    p.end();
    }
    }
    @

    ... and this does not work:

    @
    void Partitura::exportPDF()
    {
    QString fileName = QFileDialog::getSaveFileName(this, "Export PDF",
    QString(), "*.pdf");
    QPrinter printer(QPrinter::HighResolution);
    printer.setPageSize(QPrinter::A4);
    printer.setOrientation(QPrinter::Portrait);
    printer.setOutputFormat(QPrinter::PdfFormat);
    printer.setOutputFileName(fileName);

    QPainter p(&printer);
    scene->render(&p);
    p.end();
    }
    @

    scene is a QGraphicsScene object declared as global.
    The debugger returns a stack overflow when running the 2nd function.
    If i comment the line scene->render(&p); the problem disappears, but obviously i don't get the scene contents on the pdf...

    Thanks in advance.
    Tiago Campos

    [EDIT: code formatting, please wrap in @-tags, Volker]



  • Please someone, I need help on this issue.



  • Patience is a virtue.

    It's ok to push a topic after waiting a few days, it's likely to annoy your supporters to nag after one day. Don't forget that everyone here does this kind of support in their spare times. Thanks.



  • Just some ideas...

    In my experience, it is sometime useful to pass the "source" and "target" parameters to render().

    For example, your example doesn't show your call to scene.setSceneRect(). Note that render() by default uses the sceneRect as the source rect, and scales it into the target rect. Other Qt docs say the sceneRect is for "internal bookkeeping" for picking items, but doesn't it matter here also? if you don't specify a source rect parameter to render()? In my case, the sceneRect was very large, and thus when I exported to SVG, it scaled my drawing to an infinitesimal. In your case, might there be a difference in how render() works for a physical printer and for a PDF print to a file?

    It seems to me that you are not handling the responsibility to paginate (to break your drawing up into separate painting sessions (iterations) on the painter.) Could that be an issue?

    You also don't say whether the PDF file is created, and what it looks like.



  • The documentation for QPainter's constructor says, "Since the constructor cannot provide feedback when the initialization of the painter failed you should rather use begin() and end() to paint on external devices, e.g. printers."

    Try not passing the printer in the constructor and instead use the begin function to see if begin returns an error.

    @
    QPainter p;
    p.begin(&printer);
    scene->render(&p);
    p.end();
    @



  • I tried a Python version and it seems to work:

    @
    def exportPDF(self):
    fileName = "/tmp/test.pdf"
    printer = QPrinter (QPrinter.HighResolution)
    printer.setPageSize(QPrinter.A4)
    printer.setOrientation(QPrinter.Portrait)
    printer.setOutputFormat(QPrinter.PdfFormat)
    printer.setOutputFileName(fileName)

      p = QPainter(printer)
      self.scene.render(p)
      p.end()
    

    @

    Steno:
    Is it really an "external device" if you are printing to a file?

    An architecture for printing can be very confusing. For example, is a PDF file paginated? Do you use a "Print Setup" dialog to setup the pagination of a PDF file? Why not the same for SVG format? Is it because external printers and PDF files support the notion of many pages, while SVG format doesn't (but defines a viewport that is a single page?)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.