Sur cette page

Impression de graphiques

Impression d'un graphique 2D ou 3D.

L'exemple d'impression de graphiques montre comment imprimer ou exporter au format PDF des graphiques 2D et 3D.

Exécution de l'exemple

Pour exécuter l'exemple à partir de Qt CreatorOuvrez le mode Welcome et sélectionnez l'exemple à partir de Examples. Pour plus d'informations, voir Qt Creator: Tutoriel : Construire et exécuter.

Classe GraphPrinter

La fonctionnalité d'impression est mise en œuvre dans la classe GraphPrinter. Cette classe expose les fonctions suivantes :

  • La fonction generatePDF, qui fonctionne comme suit.
    • Configure le fichier PDF de sortie.

      La fonction instancie QPdfWriter avec un fichier "graph.pdf" pointé dans le dossier spécifié. La fonction spécifie également les options du fichier PDF exporté : titre, résolution, taille de la page et marges.

      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);
      }
    • Configure le traitement de l'image.

      La fonction d'aide statique paintImage dessine l'image capturée à partir de QML sur une instance de la classe QPaintDevice:

      La fonction crée un QPainter faisant référence à l'appareil.

      Pour s'assurer que le graphique est imprimé correctement, il est mis à l'échelle de la fenêtre de visualisation du peintre avec le rapport d'aspect original.

      L'indice de rendu du peintre est réglé sur un rendu d'image sans perte. Ensuite, la fonction dessine l'image dans le fichier PDF.

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

      Puisque QPdfWriter et QPrinter héritent de QPaintDevice, la fonction d'aide peut être appelée à partir de la fonction generatePDF et de la fonction print expliquées ci-dessous.

    La fonction renvoie un message d'état à afficher dans la boîte de dialogue de l'application, y compris le chemin complet du fichier exporté.

  • La fonction getPrinters renvoie une liste des imprimantes disponibles.
    QStringList GraphPrinter::getPrinters()
    {
        return QPrinterInfo::availablePrinterNames();
    }
  • La fonction print, qui fonctionne comme la fonction generatePDF, mais crée une instance QPainter renvoyant à une instance QPrinter:
    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);
    }

    La fonction renvoie un message d'état à afficher dans la boîte de dialogue de l'application.

Configuration de l'application

En plus du code de configuration de l'application, le fichier main.cpp contient du code qui crée une nouvelle instance de la classe GraphPrinter et la rend accessible à partir du code QML.

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

Configuration de la mise en page et de la capture d'images

Les graphiques 2D et 3D sont présentés dans un Stacklayout. Les utilisateurs peuvent y naviguer à l'aide d'une barre d'onglets.

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

Le composant FileDialog est utilisé pour choisir le fichier PDF à écrire. Ce composant n'a pas de représentation visuelle dans la présentation de l'application, mais son API est accessible à partir du fichier QML actuel.

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

    fileMode: FileDialog.SaveFile

Une boîte de dialogue d'impression personnalisée est créée pour sélectionner une imprimante et est déclenchée par le bouton . La boîte de dialogue récupère la liste des imprimantes disponibles et les affiche dans une liste.

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

Le bouton déclenche l'exportation PDF.

Lorsque l'exportation PDF ou l'impression est déclenchée, le code suivant est exécuté :

  • Capturez une image à l'aide de la méthode grabToImage. Le graphique actuel est l'élément de Stacklayout à l'index actuel.
  • Dans les paramètres grabToImage, nous spécifions le rappel en tant que fonction generatePDF ou print dans la classe GraphPrinter.

    Exportation PDF :

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

    Imprimer :

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

    Pour la taille, le code rend l'image à 4x la résolution réelle. Pour les graphiques en 3D, l'élément doit également être agrandi pendant la durée de l'impression :

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

Exemple de projet @ 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.