Sur cette page

Impression de graphiques

Impression d'un graphique en 2D ou en 3D.

L'exemple « Impression de graphiques » montre comment imprimer ou exporter au format PDF des graphiques en 2D et en 3D.

Graphique linéaire en 2D avec exportation au format PDF et commandes d'impression

Exécution de l'exemple

Vous pouvez exécuter l’exemple à partir de :

Classe GraphPrinter

La fonctionnalité d'impression est implémentée 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 » situé dans le dossier spécifié. Elle définit également les options du fichier PDF exporté : titre, résolution, taille de 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 une instance de ` QPainter ` référençant l’appareil.

      Pour garantir que le graphique s’affiche correctement, il est redimensionné à la taille de la fenêtre d’affichage du peintre tout en conservant son rapport d’aspect d’origine.

      Le paramètre de rendu du moteur de rendu est défini 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);
      }

      Étant donné que ` QPdfWriter ` et ` QPrinter ` héritent de ` QPaintDevice`, la fonction d’aide peut être appelée depuis la fonction ` generatePDF ` et la fonction ` print ` expliquées ci-dessous.

    La fonction renvoie un message d'état à afficher dans la boîte de dialogue de l'application, comprenant le chemin d'accès complet vers le 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 un objet ` QPainter ` faisant référence à une instance de ` 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 destiné à s’afficher dans la boîte de dialogue de messages de l’application.

Configuration de l'application

Outre le 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 depuis le code QML.

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

Configuration de la mise en page et de la capture d’image

Les graphiques 2D et 3D sont disposés dans un Stacklayout. Les utilisateurs peuvent y naviguer à l'aide d'un TabBar.

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 à générer. Ce composant n'a pas de représentation visuelle dans la mise en page de l'application, mais son API est accessible depuis le 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 ; elle est déclenchée par le bouton « Icône d'imprimante ». La boîte de dialogue récupère la liste des imprimantes disponibles et les affiche dans une vue de 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 « Icône de document » déclenche l'exportation au format PDF.

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

  • Capture d’une image à l’aide de la méthode ` grabToImage `. Le graphique actuel correspond à l’élément de la `Stacklayout` situé à l’index actuel.
  • Dans les paramètres de ` grabToImage `, nous spécifions comme callback la fonction ` generatePDF ` ou ` print ` de la classe ` GraphPrinter `.

    Exportation au format 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)
    }

    Impression :

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

    En ce qui concerne la taille, le code affiche l'image à une résolution quatre fois supérieure à la résolution réelle. Pour les graphiques en 3D, l'élément doit également être agrandi pendant toute 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 sur 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.