Auf dieser Seite

Diagramm drucken

Drucken eines 2D- oder 3D-Diagramms.

Das Beispiel „Diagrammdruck“ zeigt, wie man 2D- und 3D-Diagramme druckt oder als PDF exportiert.

2D-Liniendiagramm mit PDF-Export und Drucksteuerung

Ausführen des Beispiels

Sie können das Beispiel wie folgt ausführen:

Klasse „GraphPrinter“

Die Druckfunktionalität ist in der Klasse „ GraphPrinter “ implementiert. Die Klasse stellt folgende Funktionen bereit:

  • Die Funktion „ generatePDF “, die wie folgt funktioniert.
    • Richtet die PDF-Ausgabedatei ein.

      Die Funktion instanziiert ` QPdfWriter ` mit einer Datei „graph.pdf“, auf die im angegebenen Ordner verwiesen wird. Die Funktion legt außerdem die Optionen für die exportierte PDF-Datei fest: Titel, Auflösung, Seitengröße und Ränder.

      QFile file = QFile(path.toLocalFile());
      
      {
          QPdfWriter writer(file.fileName());
          writer.setResolution(90);
          writer.setTitle(u"Graph"_s);
          writer.setPageSize(QPageSize(image.size()));
          writer.setPageMargins(QMarginsF(0, 0, 0, 0));
          writer.newPage();
          paintImage(image, &writer);
      }
    • Richtet die Bildverarbeitung ein.

      Die statische Hilfsfunktion ` paintImage ` zeichnet das aus QML erfasste Bild auf eine Instanz der Klasse ` QPaintDevice `:

      Die Funktion erstellt ein ` QPainter `, das auf das Gerät verweist.

      Um sicherzustellen, dass das Diagramm korrekt ausgegeben wird, wird es unter Beibehaltung des ursprünglichen Seitenverhältnisses auf die Größe des Ansichtsfensters des Painters skaliert.

      Der Rendering-Hinweis für den „Painter“ wird auf verlustfreie Bildwiedergabe eingestellt. Anschließend zeichnet die Funktion das Bild in die PDF-Datei.

      static void paintImage(const QImage &image, QPaintDevice *paintDevice)
      {
          QPainter painter(paintDevice);
          const QImage finalImage = image.scaled(painter.viewport().size(), Qt::KeepAspectRatio);
          painter.setRenderHint(QPainter::LosslessImageRendering);
          painter.drawImage(finalImage.rect(), finalImage);
      }

      Da „ QPdfWriter “ und „ QPrinter “ „ QPaintDevice “ erben, kann die Hilfsfunktion aus den unten erläuterten Funktionen „ generatePDF “ und „ print “ aufgerufen werden.

    Die Funktion gibt eine Statusmeldung zurück, die im Meldungsdialog der Anwendung angezeigt wird und den vollständigen Pfad zur exportierten Datei enthält.

  • Die Funktion „ getPrinters “ gibt eine Liste der verfügbaren Drucker zurück.
    QStringList GraphPrinter::getPrinters()
    {
        return QPrinterInfo::availablePrinterNames();
    }
  • Die Funktion „ print “ funktioniert ähnlich wie die Funktion „ generatePDF “, erstellt jedoch ein „ QPainter “, das auf eine „ QPrinter “-Instanz verweist:
    QString GraphPrinter::print(const QImage &image, const QString &printerName)
    {
        QPrinterInfo printInfo = QPrinterInfo::printerInfo(printerName);
        if (printInfo.isNull())
            return tr("%1 is not a valid printer").arg(printerName);
    
        QPrinter printer(printInfo, QPrinter::HighResolution);
        printer.setOutputFormat(QPrinter::NativeFormat);
    
        paintImage(image, &printer);
    
        return tr("Printed to %1").arg(printerName);
    }

    Die Funktion gibt eine Statusmeldung zurück, die im Meldungsdialog der Anwendung angezeigt werden soll.

Anwendungskonfiguration

Zusätzlich zum Code für die Anwendungskonfiguration enthält die Datei „ main.cpp “ Code, der eine neue Instanz der Klasse „GraphPrinter“ erstellt und diese vom QML-Code aus erreichbar macht.

GraphPrinter graphPrinter;
viewer.rootContext()->setContextProperty(u"graphPrinter"_s, &graphPrinter);

Einrichtung des Layouts und der Bildaufnahme

Die 2D- und 3D-Diagramme werden in einem „Stacklayout“ angeordnet. Benutzer können darin mit einem „ TabBar “ navigieren.

TabBar {
    id: tabBar
    anchors.left: parent.left
    anchors.right: parent.right

    TabButton {
        text: "2D Graph"
        implicitHeight: 48
        icon.source: checked ? "flatten_square_fill.svg" : "flatten.svg"
        icon.height: 36
        icon.width: 36
    }

    TabButton {
        text: "3D Graph"
        implicitHeight: 48
        icon.source: checked ? "box_left_fill.svg" : "box_left.svg"
        icon.height: 36
        icon.width: 36
    }
}
Frame {
    id: tabFrame
    anchors.left: parent.left
    anchors.right: parent.right
    anchors.top: tabBar.bottom
    anchors.bottom: parent.bottom

    StackLayout {
        id: stackLayout

        anchors.fill: parent
        currentIndex: tabBar.currentIndex

        Graph2D {
            id: linegraph
        }

        Graph3D {
            id: bargraph
        }
    }
}

Die „FileDialog“-Komponente dient zur Auswahl der zu erstellenden PDF-Datei. Diese Komponente ist im Anwendungslayout nicht sichtbar, ihre API ist jedoch über die aktuelle QML-Datei zugänglich.

FileDialog {
    id: dialog
    currentFolder: StandardPaths.writableLocation(StandardPaths.PicturesLocation)
    nameFilters: ["PDF files (*.pdf)"]
    defaultSuffix: "pdf"

    fileMode: FileDialog.SaveFile

Zur Auswahl eines Druckers wird ein benutzerdefinierter Druckdialog erstellt, der über die Schaltfläche „ Druckersymbol “ ausgelöst wird. Der Dialog ruft die Liste der verfügbaren Drucker ab und zeigt sie in einer Listenansicht an.

Dialog {
    id: printerDialog
    anchors.centerIn: parent
    contentHeight: printerListView.height
    contentWidth: printerListView.width

    title: qsTr("Available Printers")
    modal: true

    onOpened: {
        printerModel.clear()
        var printers = graphPrinter.getPrinters()
        printers.forEach((x, i) => printerModel.append({
                                                           "name": x
                                                       }))
    }
...
contentItem: Rectangle {
    id: printerItem
    height: printerListView.height
    width: printerListView.width
    color: mainView.item.theme.plotAreaBackgroundColor

    ListView {
        id: printerListView
        height: 100
        width: 200
        clip: true

        model: printerModel
        delegate: printerDelegate
        highlight: Rectangle {
            color: mainView.item.theme.grid.subColor
        }
    }
}

Die Schaltfläche „ Dokumentensymbol “ löst den PDF-Export aus.

Wenn entweder der PDF-Export oder der Druckvorgang ausgelöst wird, wird der folgende Code ausgeführt:

  • Erfassen Sie ein Bild mithilfe der Methode „ grabToImage “. Das aktuelle Diagramm ist das Element des StackLayouts am aktuellen Index.
  • In den Parametern von „ grabToImage “ geben wir als Callback die Funktion „ generatePDF “ oder „ print “ aus der Klasse „ GraphPrinter “ an.

    PDF-Export:

    onAccepted: {
        mainView.prepareForPrint()
    
        mainView.item.grabToImage(function (result) {
            message.title = "Save PDF"
            message.text = "PDF saved to " + graphPrinter.generatePDF(
                        dialog.selectedFile, result.image)
            message.open()
        }, mainView.outputsize)
    }

    Drucken:

    onAccepted: {
        var selectedPrinter = printerModel.get(printerListView.currentIndex)
        mainView.prepareForPrint()
        mainView.item.grabToImage(function (result) {
            message.title = "Print"
            message.text = graphPrinter.print(result.image,
                                              selectedPrinter.name)
            message.open()
        }, mainView.outputsize)
    }
    
    onClosed: {
        mainView.cleanAfterPrint()
    }

    Was die Größe betrifft, sorgt der Code dafür, dass das Bild mit der vierfachen tatsächlichen Auflösung dargestellt wird. Bei 3D-Diagrammen muss das Element zudem für die Dauer des Druckvorgangs erweitert werden:

    function prepareForPrint() {
        if (stackLayout.currentIndex === 1) {
            var newsize = Qt.size(bargraph.width * 4, bargraph.height * 4)
    
            // check that we do not exceed maximum texture size
            if (newsize.width * Screen.devicePixelRatio > graphPrinter.maxTextureSize() ) {
                // scale to 25% under max texture size to be on the safe side; some GPUs seem
                // to glitch when using the abosulute max
                var ratio = (newsize.width * Screen.devicePixelRatio * 1.25)
                        / graphPrinter.maxTextureSize()
                newsize.width /= ratio
                newsize.height /= ratio
            }
            outputsize.width = Math.round(newsize.width)
            outputsize.height = Math.round(newsize.height)
    
            // resize the bar graph to match the PDF output size
            item.width = outputsize.width
            item.height = outputsize.height
        } else {
            outputsize = Qt.size(linegraph.width * 4, linegraph.height * 4)
        }
    }
    
    function cleanAfterPrint() {
        if (stackLayout.currentIndex === 1) {
            // resize the bar graph back to the actual visual size
            item.width = stackLayout.width
            item.height = stackLayout.height
        }
    }

Beispielprojekt @ code.qt.io

© 2026 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.