Printing widgets not as bitmap, but in a vector based format
-
Hi there,
I already searched a lot but didn't find anything of use about this topic, so I'd like to ask here.
In my application I'd like to print a widget (a QTreeView, I don't think it matters).
Based on an example I found I use the following code (PySide)
[code]
printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
printer.setOutputFileName("print.pdf")
painter = QtGui.QPainter()
painter.begin(printer)self.my_widget.render(painter, QtCore.QPoint())
painter.end()
[/code]Unfortunately, the PDF file is quite large, because it contains the widget as one big bitmap.
Strangely, modifying the above code for usage with QSvgGenerator however:
[code]
printer = QtSvg.QSvgGenerator()
printer.setFileName("print.svg")
painter = QtGui.QPainter()
painter.begin(printer)self.my_widget.render(painter, QtCore.QPoint())
painter.end()
[/code]... yields a nice SVG drawing of my widget -- composed of separate SVG entities, no bitmaps at all.
I also tried:
- ... to read the produced SVG image and print it out again like above, using QSvgRenderer, but the produced PDF is rasterised, too.
- Not using QPrinter::setOutputFilename() and "really" printing using a PDF renderer (FreePDF XP) also yielded a raster PDF file.
- Printing the SVG out of inkscape using the same PDF printer produces a nice vector-based PDF file ...
How can I configure or modify QPrinter to render the output vector based as well?
Digging in the source code I found no real hints about this after over an hour -- the API is quite complex. So I hope anybody has experience with this and could point me in the right direction about how to set up or derive QPrinter so that it outputs vector data.
Regards&thanks for your time,
Björn
-
I had the same question and found a solution. Posting here for anyone trying to figure out how to print QWidgets to a PDF as vectors and text.
I did this in C++, but it should translate to Python roughly as follows:
@
// First render the widget to a QPicture, which stores QPainter commands.
QPicture pic;
QPainter picPainter(pic);
self.my_widget.render(picPainter);
picPainter.end();// Set up the printer printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution) printer.setOutputFormat(QtGui.QPrinter.PdfFormat) printer.setOutputFileName("print.pdf") // Finally, draw the QPicture to your printer painter = QtGui.QPainter() painter.begin(printer) painter.drawPicture(QtCore.QPointF(0, 0), pic); painter.end()
@
The reason this extra step of drawing to a QPicture is necessary is that QWidget uses a different code path when printing to a printer than printing to any other QPaintDevice. For some reason it thinks you must want a bitmap if you're printing, so it renders to a QPixmap explicitly, then draws the pixmap to the painter. Rendering to a QPicture circumvents that behavior.
I discovered this by looking through the Qt source code. I could not find any documentation describing this behavior.
Hope that helps!
-
Can you post c++ equilavent of this code. I try this but not work. I try to export a widget as pdf.
@ QPicture pic;
QPainter picPainter(pic);
ui->widget->render(picPainter);
picPainter.end();QPrinter printer(QPrinter::HighResolution); printer.setOutputFormat(QPrinter::PdfFormat); printer.setOutputFileName("12.pdf"); QPainter paint(); paint().begin(&printer); paint().drawPicture(0,20,pic); paint().end();
@
-
Can you post c++ equilavent of this code. I try this but not work. I try to export a widget as pdf.
@ QPicture pic;
QPainter picPainter(pic);
ui->widget->render(picPainter);
picPainter.end();QPrinter printer(QPrinter::HighResolution); printer.setOutputFormat(QPrinter::PdfFormat); printer.setOutputFileName("12.pdf"); QPainter paint(); paint().begin(&printer); paint().drawPicture(0,20,pic); paint().end();
@
-
Hi,
No tested but it should rather be something like:
@
QPicture pic;
QPainter picPainter(&pic);
ui->widget->render(&picPainter);QPrinter printer(QPrinter::HighResolution);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName("12.pdf");QPainter painter(&printer);
painter.drawPicture(0,20,pic);
painter.end();
@ -
Hi,
No tested but it should rather be something like:
@
QPicture pic;
QPainter picPainter(&pic);
ui->widget->render(&picPainter);QPrinter printer(QPrinter::HighResolution);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName("12.pdf");QPainter painter(&printer);
painter.drawPicture(0,20,pic);
painter.end();
@ -
SGaist, your code works. but now pdf is empty white paper. nothing in it. I want to export my widget to pdf with high quality. I found another way to do this. but quality is low. There is some shapes in widget and these shapes look ugly with this code. How can I export my widget with high quality?
Thank you and sorry for my English
the code I found:
@QPixmap pixmap;
pixmap=QPixmap::grabWindow(ui->widget->winId());QPrinter printer(QPrinter::HighResolution);
printer.setOrientation(QPrinter::Landscape);
printer.setOutputFormat(QPrinter::PdfFormat);
//printer.setPageMargins(10,10,10,10,QPrinter::Millimeter);printer.setOutputFileName("12.pdf");
QPainter painter(&printer);
QRect rect=painter.viewport();
QSize size=pixmap.size();size.scale(rect.size(), Qt::KeepAspectRatio);
painter.setViewport(rect.x(), rect.y(), size.width(), size.height());
painter.setWindow(pixmap.rect());int pdfX=680-(640/20);
int pdfY=460-(460/10);painter.drawText(0, 0, 640, 20, Qt::AlignHCenter, "graph");
painter.drawPixmap(0, 20, pdfX, pdfY, pixmap);@ -
SGaist, your code works. but now pdf is empty white paper. nothing in it. I want to export my widget to pdf with high quality. I found another way to do this. but quality is low. There is some shapes in widget and these shapes look ugly with this code. How can I export my widget with high quality?
Thank you and sorry for my English
the code I found:
@QPixmap pixmap;
pixmap=QPixmap::grabWindow(ui->widget->winId());QPrinter printer(QPrinter::HighResolution);
printer.setOrientation(QPrinter::Landscape);
printer.setOutputFormat(QPrinter::PdfFormat);
//printer.setPageMargins(10,10,10,10,QPrinter::Millimeter);printer.setOutputFileName("12.pdf");
QPainter painter(&printer);
QRect rect=painter.viewport();
QSize size=pixmap.size();size.scale(rect.size(), Qt::KeepAspectRatio);
painter.setViewport(rect.x(), rect.y(), size.width(), size.height());
painter.setWindow(pixmap.rect());int pdfX=680-(640/20);
int pdfY=460-(460/10);painter.drawText(0, 0, 640, 20, Qt::AlignHCenter, "graph");
painter.drawPixmap(0, 20, pdfX, pdfY, pixmap);@ -
Also I tried to export Qimage to pdf but again quality is low.
@QPrinter printer;
printer.setOrientation(QPrinter::Portrait);
printer.setOutputFileName("test.pdf");
printer.setOutputFormat(QPrinter::PdfFormat);QImage image("/home/asd/a.png");
QPainter painter;
painter.setRenderHint(QPainter::Antialiasing, true);
painter.begin(&image);
painter.end();QPainter p;
p.begin(&printer);
p.drawImage(0, 0, image);
p.end();@"http://www.qtcentre.org/threads/11236-2-questions-on-QPrint-QImage-PDF":http://www.qtcentre.org/threads/11236-2-questions-on-QPrint-QImage-PDF
-
Also I tried to export Qimage to pdf but again quality is low.
@QPrinter printer;
printer.setOrientation(QPrinter::Portrait);
printer.setOutputFileName("test.pdf");
printer.setOutputFormat(QPrinter::PdfFormat);QImage image("/home/asd/a.png");
QPainter painter;
painter.setRenderHint(QPainter::Antialiasing, true);
painter.begin(&image);
painter.end();QPainter p;
p.begin(&printer);
p.drawImage(0, 0, image);
p.end();@"http://www.qtcentre.org/threads/11236-2-questions-on-QPrint-QImage-PDF":http://www.qtcentre.org/threads/11236-2-questions-on-QPrint-QImage-PDF
-
Andre, I have graphs (pie chart and "qcustomplot":http://www.qcustomplot.com/) and explanations(qlabel) in widget. I want to export these graphs and texts to pdf. codes which I used can export but quality is low. I want to export with high quality.
-
Andre, I have graphs (pie chart and "qcustomplot":http://www.qcustomplot.com/) and explanations(qlabel) in widget. I want to export these graphs and texts to pdf. codes which I used can export but quality is low. I want to export with high quality.
-
I figured as much.
I've had similar issues last year. The solution I wend for is scaling up my rendering to match the output device. That really is the only way to get a good-looking result I found. That also means calculating a good font size for your items, and taking into account that some elements don't get too small (a hairline at 1200dpi will look really, really, really fine). I ended up having to deal with that on an element-by-element basis.
Note that you're dealing with about an order of magnitude higher resolutions than what you're getting on-screen.
Our printouts and PDF's look very crisp and clear now...
-
I figured as much.
I've had similar issues last year. The solution I wend for is scaling up my rendering to match the output device. That really is the only way to get a good-looking result I found. That also means calculating a good font size for your items, and taking into account that some elements don't get too small (a hairline at 1200dpi will look really, really, really fine). I ended up having to deal with that on an element-by-element basis.
Note that you're dealing with about an order of magnitude higher resolutions than what you're getting on-screen.
Our printouts and PDF's look very crisp and clear now...
-
I had the same question and found a solution. Posting here for anyone trying to figure out how to print QWidgets to a PDF as vectors and text.
I did this in C++, but it should translate to Python roughly as follows:
@
// First render the widget to a QPicture, which stores QPainter commands.
QPicture pic;
QPainter picPainter(pic);
self.my_widget.render(picPainter);
picPainter.end();// Set up the printer printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution) printer.setOutputFormat(QtGui.QPrinter.PdfFormat) printer.setOutputFileName("print.pdf") // Finally, draw the QPicture to your printer painter = QtGui.QPainter() painter.begin(printer) painter.drawPicture(QtCore.QPointF(0, 0), pic); painter.end()
@
The reason this extra step of drawing to a QPicture is necessary is that QWidget uses a different code path when printing to a printer than printing to any other QPaintDevice. For some reason it thinks you must want a bitmap if you're printing, so it renders to a QPixmap explicitly, then draws the pixmap to the painter. Rendering to a QPicture circumvents that behavior.
I discovered this by looking through the Qt source code. I could not find any documentation describing this behavior.
Hope that helps!
@umundane
I realize that this thread is really (really, really) old, but I just wanted to say that this remains an issue today eight years later, and this solution - render to a QImage then draw the image to the QPrinter - (still) works like a charm! Thanks!