En esta página

Impresión de gráficos

Impresión de un gráfico 2D o 3D.

El ejemplo Impresión de gráficos muestra cómo imprimir o exportar a PDF gráficos 2D y 3D.

Ejecución del ejemplo

Para ejecutar el ejemplo desde Qt Creatorabra el modo Welcome y seleccione el ejemplo de Examples. Para más información, consulte Qt Creator: Tutorial: Construir y ejecutar.

Clase GraphPrinter

La funcionalidad de impresión se implementa en la clase GraphPrinter. La clase expone estas funciones:

  • La función generatePDF, que funciona de la siguiente manera.
    • Establece el archivo PDF de salida.

      La función instancia QPdfWriter con un archivo "graph.pdf" apuntado en la carpeta especificada. La función también especifica las opciones para el archivo PDF exportado: título, resolución, tamaño de página y márgenes.

      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);
      }
    • Configura el procesamiento de imágenes.

      La función de ayuda estática paintImage dibuja la imagen capturada desde QML en una instancia de la clase QPaintDevice:

      La función crea un QPainter que hace referencia al dispositivo.

      Para garantizar que el gráfico se imprime correctamente, se escala al tamaño de la ventana gráfica del pintor con la relación de aspecto original.

      La sugerencia de renderizado del pintor se establece en renderizado de imagen sin pérdidas. A continuación, la función dibuja la imagen en el archivo 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);
      }

      Dado que QPdfWriter y QPrinter heredan de QPaintDevice, la función de ayuda puede llamarse desde la función generatePDF y la función print que se explican a continuación.

    La función devuelve un mensaje de estado que se mostrará en el cuadro de diálogo de mensajes de la aplicación, incluida la ruta completa al archivo exportado.

  • La función getPrinters devuelve una lista de impresoras disponibles.
    QStringList GraphPrinter::getPrinters()
    {
        return QPrinterInfo::availablePrinterNames();
    }
  • La función print, que funciona como la función generatePDF, pero crea una instancia QPainter que remite a 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 función devuelve un mensaje de estado que se mostrará en el cuadro de diálogo de mensajes de la aplicación.

Configuración de la aplicación

Además del código de configuración de la aplicación, el archivo main.cpp contiene código que crea una nueva instancia de la clase GraphPrinter y la hace accesible desde el código QML.

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

Configuración del diseño y captura de imágenes

Los gráficos 2D y 3D se presentan en un Stacklayout. Los usuarios pueden navegar por él con una 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
        }
    }
}

El componente FileDialog se utiliza para elegir el archivo PDF que se va a escribir. Este componente no tiene representación visual en el diseño de la aplicación, pero su API es accesible desde el archivo QML actual.

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

    fileMode: FileDialog.SaveFile

Se crea un diálogo de impresión personalizado para seleccionar una impresora, que se activa con el botón . El diálogo recupera la lista de impresoras disponibles y las muestra en una vista de lista.

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

El botón activa la exportación a PDF.

Cuando se activa la exportación a PDF o la impresión, se ejecuta el siguiente código:

  • Captura una imagen utilizando el método grabToImage. El gráfico actual es el elemento del Stacklayout en el índice actual.
  • En los parámetros grabToImage, especificamos la llamada de retorno como la función generatePDF o print en la clase GraphPrinter.

    Exportación a 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)
    }

    Imprimir:

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

    Para el tamaño, el código hace que la imagen se renderice a 4x la resolución real. Para los gráficos 3D, el elemento también debe expandirse mientras dure la impresión:

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

Proyecto de ejemplo @ 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.