I'm using Qt charts
module to draw a pie chart directly on a PDF file.
Here's the problem:
For some unknown reason, the chart needs to be displayed with show()
before it's rendered to the PDF for it's size to be OK (left image).
On the other hand, I don't want to have to display every chart on the screen since my application generates a lot of them. However, if the chart is not displayed in a window with show()
, then the drawing gets too small in the PDF (right image) even though the size of the chart is properly set with resize()
.
(black borders were added to these images to improve visualization)
Displaying all charts on a window before they are rendered to the PDF is not an option. The fact that the chart needs to execute show()
for QPainter to draw it to the PDF correctly seems to indicate that without it, QPainter ignores the chart's dimension.
On a side note, show()
opens the window but it takes several seconds for the
chart to appear, so rendering is very very slow, another reason for me not to want to display the charts.
So here are my main questions:
Here is a Minimal, Complete, and Verifiable example...
main.cpp:
#include <QApplication>
#include <QtCharts/QChartView>
#include <QtCharts/QPieSeries>
#include <QtCharts/QPieSlice>
#include <QPainter>
#include <QPdfWriter>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtCharts::QChartView* chartView = new QtCharts::QChartView();
chartView->setRenderHint(QPainter::Antialiasing);
chartView->resize(640, 480);
QtCharts::QChart* chart = chartView->chart();
chart->setTitle("Beautiful Pie Chart");
chart->legend()->hide();
QtCharts::QPieSeries* series = new QtCharts::QPieSeries();
float hits = 73.0f, misses = 27.0f;
series->append("Hits", hits);
series->append("Misses", misses);
QtCharts::QPieSlice* hit_slice = series->slices().at(0);
hit_slice->setBrush(QColor(87, 147, 243)); // blue
QtCharts::QPieSlice* miss_slice = series->slices().at(1);
miss_slice->setBrush(QColor(221, 68, 68)); // red
chart->addSeries(series);
// Due to Qt bug, must show() the chart before render()
// or it will be draw too tiny in the PDF by QPainter
chartView->show();
QPdfWriter writer("out.pdf");
writer.setCreator("https://stackoverflow.com/users/176769/karlphillip");
writer.setPageSize(QPagedPaintDevice::A4);
QPainter painter(&writer);
chartView->render(&painter);
painter.end();
return a.exec();
}
QtCharts_PDF.pro:
QT += core gui charts
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = QtCharts_PDF
TEMPLATE = app
SOURCES += main.cpp
One way to bypass this problem is to create a QPixmap
from the QChartView
and draw the pixmap into the PDF:
QPixmap pix = chartView->grab();
int h = painter.window().height()*0.4;
int w = h * 1.3;
int x = (painter.window().width() / 2) - (w/2);
int y = (painter.window().height() / 2) - (h/2);
chartView->resize(w, h);
painter.drawPixmap(x, y, w, h, pix);
This is kinda like taking a screenshot of the widget and rendering it to the file.
QPainter.drawPixmap()
let's you specify the size and location of the drawing in the PDF. It's not ideal, but it will do for now. I know, it's a hack, it works, but I'm still looking for a better solution.