Graph Printing
Printing a 2D or 3D Graph to a PDF.
The Graph Printing example demonstrates how to print or export to PDF 2D and 3D graphs.
Running the Example
To run the example from Qt Creator, open the Welcome mode and select the example from Examples. For more information, see Qt Creator: Tutorial: Build and run.
GraphPrinter class
The printing functionality is implemented in the GraphPrinter
class. The class exposes these functions:
- The
generatePDF
function, which works as follows.- Sets up the output PDF file.
The function instantiates QPdfWriter with a "graph.pdf" file pointed in the specified folder. The function also specifies the options for the exported PDF file: title, resolution, page size, and margins.
const QFile file = QFile(path.toLocalFile() + QStringLiteral("/graph.pdf")); QPdfWriter writer(file.fileName()); writer.setResolution(90); writer.setTitle("Graph"); writer.setPageSize(QPageSize(image.size())); writer.setPageMargins(QMarginsF(0, 0, 0, 0)); writer.newPage();
- Sets up image processing.
The function creates a QPainter referring to the previously created QPdfWriter.
To ensure the graph is printed correctly, it is scaled to the painter's viewport size with the original aspect ratio.
The painter's rendering hint is set to lossless image rendering. After this, the function draws the image to the PDF file.
- Sets up the output PDF file.
- The
print
function, which works like thegeneratePDF
function, but creates a QPainter referring a QPrinter instance:void GraphPrinter::print(const QImage &image, const QString printerName) { QPrinterInfo printInfo = QPrinterInfo::printerInfo(printerName); if (printInfo.isNull()) { qWarning("%ls is not a valid printer", qUtf16Printable(printerName)); return; } QPrinter printer(printInfo, QPrinter::HighResolution); printer.setOutputFormat(QPrinter::NativeFormat); QPainter painter(&printer); const QImage finalImage = image.scaled(painter.viewport().size(), Qt::KeepAspectRatio); painter.setRenderHint(QPainter::LosslessImageRendering); painter.drawImage(finalImage.rect(), finalImage); qInfo("printed image with %ls", qUtf16Printable(printerName)); }
- The
getPrinters
function returns a list of available printers.QStringList GraphPrinter::getPrinters() { return QPrinterInfo::availablePrinterNames(); }
Application setup
In addition to the application setup code, the main.cpp
file contains code that creates a new instance of the GraphPrinter class and makes it reachable from the QML code.
GraphPrinter graphPrinter; viewer.rootContext()->setContextProperty("graphPrinter", &graphPrinter);
Setting up the layout and image capture
The 2D and 3D graphs are laid out in a Stacklayout. Users can navigate it with a TabBar.
TabBar { id: tabBar anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right TabButton { text: "2D Graph" implicitHeight: 50 } TabButton { text: "3D Graph" implicitHeight: 50 } } StackLayout { id: stackLayout anchors.top: tabBar.bottom anchors.bottom: parent.bottom width: parent.width currentIndex: tabBar.currentIndex Graph2D {} Graph3D {} }
The FolderDialog component is used to select a folder for saving an exported file. This component has no visual representation in the application layout, but its API is accessible from the current QML file.
The Button invokes a folder dialog.
FolderDialog { id: dialog onAccepted: console.log("Saving to " + currentFolder) } ... Button { id: setFolderButton onClicked: dialog.open() text: "Set save location" Layout.margins: 5 }
A custom printing dialog is created for selecting a printer. The Dialog retrieves the list of available printers and displays them in a list view.
Dialog { id: printerDialog x: parent.width * 0.5 - width * 0.5 y: parent.height * 0.5; contentHeight: 200 contentWidth: 200 title: qsTr("Available printers") modal: true property var item: stackLayout.itemAt(stackLayout.currentIndex) onOpened: { printerModel.clear() var printers = graphPrinter.getPrinters() printers.forEach((x,i) => printerModel.append({"name": x})) } ... contentItem: Item { id: printerItem height: 200 width: parent.width ListView { id: printerListView height: 200 width: 200 clip: true model: printerModel delegate: printerDelegate highlight: Rectangle {color: "darkgrey"} } }
The Save to PDF button and Print button in the printing dialog run the following code:
- Capture an image using the
grabToImage
method. The current graph is the Stacklayout's item at the current index. - In the
grabToImage
parameters, we specify the callback as thegeneratePDF
orprint
function in theGraphPrinter
class.For the size, the code makes the image render at a 7282 by 4096 resolution. For 3D graphs, the item must also be expanded for the duration of printing.
Button { id: captureButton text: "Save to PDF" Layout.margins: 5 property var item: stackLayout.itemAt(stackLayout.currentIndex) onPressed: { if (stackLayout.currentIndex === 1) { item.width = 7282 item.height = 4096 } item.grabToImage(function(result) { graphPrinter.generatePDF(dialog.currentFolder, result.image) }, Qt.size(7282, 4096)) } onReleased: { if (stackLayout.currentIndex === 1) { item.width = mainView.width item.height = mainView.height } } } ... onAccepted: { var selectedPrinter = printerModel.get(printerListView.currentIndex) if (stackLayout.currentIndex === 1) { item.width = 7282 item.height = 4096 } item.grabToImage(function(result) { graphPrinter.print(result.image, selectedPrinter.name) }, Qt.size(7282, 4096)) } onClosed: { if (stackLayout.currentIndex === 1) { item.width = mainView.width item.height = mainView.height } }
© 2024 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.