Drucken von Grafiken

Drucken eines 2D- oder 3D-Diagramms.

Das Beispiel zum Drucken von Diagrammen zeigt, wie 2D- und 3D-Diagramme gedruckt oder als PDF exportiert werden können.

Ausführen des Beispiels

Zum Ausführen des Beispiels von Qt Creatorauszuführen, öffnen Sie den Modus Welcome und wählen Sie das Beispiel unter Examples aus. Weitere Informationen finden Sie unter Erstellen und Ausführen eines Beispiels.

GraphPrinter-Klasse

Die Druckfunktionalität ist in der Klasse GraphPrinter implementiert. Die Klasse stellt diese Funktionen zur Verfügung:

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

      Die Funktion instanziiert QPdfWriter mit einer "graph.pdf"-Datei, die auf den angegebenen Ordner zeigt. Die Funktion legt auch die Optionen für die exportierte PDF-Datei fest: Titel, Auflösung, Seitengröße und Ränder.

      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();
    • Richtet die Bildverarbeitung ein.

      Die Funktion erstellt eine QPainter mit Verweis auf die zuvor erstellte QPdfWriter.

      Um sicherzustellen, dass das Diagramm korrekt gedruckt wird, wird es auf die Größe des Ansichtsfensters des Malers mit dem ursprünglichen Seitenverhältnis skaliert

      Der Rendering-Hinweis des Painters wird auf verlustfreies Bildrendering gesetzt. Danach zeichnet die Funktion das Bild in die PDF-Datei.

      QPainter painter(&writer);
      const QImage finalImage = image.scaled(painter.viewport().size(), Qt::KeepAspectRatio);
      painter.setRenderHint(QPainter::LosslessImageRendering);
      painter.drawImage(finalImage.rect(), finalImage);

    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, die wie die Funktion generatePDF funktioniert, aber eine QPainter erstellt, die auf eine QPrinter-Instanz verweist:
    QString GraphPrinter::print(const QImage &image, const QString printerName)
    {
        QPrinterInfo printInfo = QPrinterInfo::printerInfo(printerName);
        if (printInfo.isNull())
            return QLatin1String("%1 is not a valid printer").arg(printerName);
    
        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);
    
        return QLatin1String("Printed to %1").arg(printerName);
    }

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

Einrichtung der Anwendung

Zusätzlich zum Code für die Einrichtung der Anwendung enthält die Datei main.cpp Code, der eine neue Instanz der GraphPrinter-Klasse erzeugt und sie vom QML-Code aus erreichbar macht.

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

Einrichten des Layouts und der Bilderfassung

Die 2D- und 3D-Diagramme werden in einem Stacklayout angeordnet. Benutzer können darin mit einer 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 FolderDialog-Komponente wird verwendet, um einen Ordner zum Speichern der exportierten Datei auszuwählen. Diese Komponente hat keine visuelle Darstellung im Anwendungslayout, aber ihre API ist über die aktuelle QML-Datei zugänglich.

Die Schaltfläche ruft einen Ordnerdialog auf.

FolderDialog {
    id: dialog
    property bool folderset: false
    onAccepted: {
        folderset = true
        message.title = "Folder Set"
        message.text = "Folder set to " + selectedFolder.toString().replace(/^(file:\/{3})/, "")
        message.open()
    }
}
...
Button {
    id: setFolderButton
    ...
onClicked: dialog.open()
}

Für die Auswahl eines Druckers wird ein benutzerdefinierter Druckdialog erstellt, der über die Schaltfläche aufgerufen 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 löst den PDF-Export aus, wenn bereits ein Ordner ausgewählt wurde.

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

  • Erfassen Sie ein Bild mit der Methode grabToImage. Das aktuelle Diagramm ist das Element des Stacklayouts am aktuellen Index.
  • In den Parametern grabToImage geben wir den Callback als Funktion generatePDF oder print in der Klasse GraphPrinter an.

    PDF-Export:

    onPressed: {
        if (!dialog.folderset) {
            message.title = "No Folder Set"
            message.text = "Please select folder first"
            message.open()
        } else {
            mainView.prepareForPrint()
            mainView.item.grabToImage(function (result) {
                message.title = "Save PDF"
                message.text = "PDF saved to " + graphPrinter.generatePDF(
                            dialog.currentFolder, result.image)
                message.open()
            }, mainView.outputsize)
        }
    }
    
    onReleased: {
        mainView.cleanAfterPrint()
    }

    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()
    }

    Für die Größe sorgt der Code dafür, dass das Bild mit der 4-fachen tatsächlichen Auflösung gerendert wird. Bei 3D-Diagrammen muss das Element auch für die Dauer des Drucks erweitert werden:

    function prepareForPrint() {
        if (stackLayout.currentIndex === 1) {
            outputsize = Qt.size(bargraph.width * 4, bargraph.height * 4)
            // 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 = mainView.width
            item.height = mainView.height
        }
    }

Beispielprojekt @ code.qt.io

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