このページでは

グラフの印刷

2Dまたは3Dグラフの印刷

グラフ印刷の例では、2Dおよび3Dのグラフを印刷またはPDFにエクスポートする方法を示します。

例を実行する

から例を実行するには Qt Creatorからサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳細については、Qt Creator:Tutorialを参照してください:ビルドと実行

GraphPrinter クラス

印刷機能はGraphPrinter クラスに実装されています。このクラスは以下の関数を公開しています:

  • generatePDF 関数は次のように動作します。
    • 出力PDFファイルをセットアップします。

      この関数は、QPdfWriter を、指定されたフォルダを指す "graph.pdf" ファイルでインスタンス化します。この関数はまた、書き出されるPDFファイルのオプション(タイトル解像度ページサイズ余白)を指定します。

      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);
      }
    • 画像処理を設定。

      静的ヘルパーpaintImage 関数は、QML から取り込んだ画像をQPaintDevice クラスのインスタンスに描画します:

      この関数はデバイスを参照するQPainter を生成します。

      グラフが正しく印刷されるように、元のアスペクト比のままペインターのビューポートサイズにスケーリングされます。

      ペインターのレンダリングヒントはロスレス画像レンダリングに設定されます。この後、関数は画像を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);
      }

      QPdfWriterQPrinterQPaintDevice を継承しているので、このヘルパー関数はgeneratePDF 関数と、以下に説明するprint 関数から呼び出すことができます。

    この関数は、アプリケーションのメッセージダイアログに表示されるステータスメッセージ(エクスポートされたファイルのフルパスを含む)を返します。

  • getPrinters 関数は、利用可能なプリンタのリストを返します。
    QStringList GraphPrinter::getPrinters()
    {
        return QPrinterInfo::availablePrinterNames();
    }
  • print 関数は、generatePDF 関数と同様に動作しますが、QPrinter インスタンスを参照するQPainter を作成します:
    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);
    }

    この関数は、アプリケーションのメッセージダイアログに表示されるステータスメッセージを返します。

アプリケーションのセットアップ

アプリケーションのセットアップコードに加えて、main.cpp ファイルには、GraphPrinter クラスの新しいインスタンスを作成し、QML コードからアクセスできるようにするコードが含まれています。

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

レイアウトと画像キャプチャのセットアップ

2Dと3DのグラフはStacklayoutにレイアウトされます。ユーザは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
        }
    }
}

FileDialogコンポーネントは、書き込むPDFファイルを選択するために使用されます。このコンポーネントはアプリケーションレイアウトでは視覚的に表現されていませんが、そのAPIはカレントQMLファイルからアクセス可能です。

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

    fileMode: FileDialog.SaveFile

カスタム印刷ダイアログはプリンタを選択するために作成され、 ボタンで起動されます。ダイアログは利用可能なプリンタのリストを取得し、リストビューに表示します。

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

ボタンを押すと PDF エクスポートが開始されます。

PDF書き出しまたは印刷のいずれかがトリガーされると、以下のコードが実行されます:

  • grabToImage メソッドを使って画像をキャプチャ。現在のグラフは、現在のインデックスのStacklayoutのアイテムです。
  • grabToImage パラメータで、GraphPrinter クラスのgeneratePDF またはprint 関数としてコールバックを指定します。

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

    印刷:

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

    サイズについては、コードは画像を実際の解像度の4倍でレンダリングさせます。3Dグラフの場合、印刷の間、アイテムも拡大する必要があります:

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

プロジェクト例 @ 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.