Java | 複数の入力をまとめて List に格納するサンプル

Java Java
スポンサーリンク

では、前回の「タイトル付き折れ線グラフ」をさらに発展させて、PDFに複数ページ出力(1ページ目にグラフ、2ページ目に統計値表)を作るサンプルを紹介します。

ここでは外部ライブラリ iText を利用します(Mavenなら com.itextpdf:itextpdf:5.x を依存関係に追加)。

サンプルコード:複数ページPDF出力

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.util.*;
import javax.imageio.ImageIO;

import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;

public class ChartMultiPagePDF extends JPanel {
    private List<Map<Integer, Integer>> datasets;
    private List<String> labels;
    private String chartTitle = "複数データセットの折れ線グラフ";

    public ChartMultiPagePDF(List<Map<Integer, Integer>> datasets, List<String> labels) {
        this.datasets = datasets;
        this.labels = labels;
        setPreferredSize(new Dimension(600, 400));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        if (datasets == null || datasets.isEmpty()) return;

        Graphics2D g2 = (Graphics2D) g;
        int width = getWidth();
        int height = getHeight();

        // タイトル
        g2.setFont(new Font("SansSerif", Font.BOLD, 16));
        FontMetrics fm = g2.getFontMetrics();
        int titleWidth = fm.stringWidth(chartTitle);
        g2.drawString(chartTitle, (width - titleWidth) / 2, 25);

        // 軸
        g2.setFont(new Font("SansSerif", Font.PLAIN, 12));
        g2.setColor(Color.BLACK);
        g2.drawLine(50, height - 50, width - 20, height - 50);
        g2.drawLine(50, 30, 50, height - 50);

        // 最大値
        int maxCount = 0;
        for (Map<Integer, Integer> data : datasets) {
            if (!data.isEmpty()) {
                maxCount = Math.max(maxCount, Collections.max(data.values()));
            }
        }

        // データセット描画
        Color[] colors = {Color.RED, Color.BLUE};
        int datasetIndex = 0;
        for (Map<Integer, Integer> data : datasets) {
            g2.setColor(colors[datasetIndex % colors.length]);
            List<Integer> keys = new ArrayList<>(data.keySet());
            Collections.sort(keys);

            int prevX = -1, prevY = -1;
            int i = 0;
            for (int key : keys) {
                int count = data.get(key);
                int x = 50 + (i * (width - 100) / (keys.size() - 1));
                int y = height - 50 - (int) ((double) count / maxCount * (height - 100));

                g2.fillOval(x - 3, y - 3, 6, 6);
                if (prevX != -1) g2.drawLine(prevX, prevY, x, y);

                prevX = x;
                prevY = y;
                i++;
            }
            datasetIndex++;
        }
    }

    public static void main(String[] args) {
        // ダミーデータ
        Map<Integer, Integer> dataset1 = new LinkedHashMap<>();
        dataset1.put(1, 3);
        dataset1.put(2, 5);
        dataset1.put(3, 2);
        dataset1.put(4, 7);

        Map<Integer, Integer> dataset2 = new LinkedHashMap<>();
        dataset2.put(1, 2);
        dataset2.put(2, 4);
        dataset2.put(3, 6);
        dataset2.put(4, 5);

        List<Map<Integer, Integer>> datasets = Arrays.asList(dataset1, dataset2);
        List<String> labels = Arrays.asList("データセット1", "データセット2");

        ChartMultiPagePDF panel = new ChartMultiPagePDF(datasets, labels);

        try {
            // Swingパネルを画像化
            BufferedImage image = new BufferedImage(600, 400, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2 = image.createGraphics();
            panel.paint(g2);
            g2.dispose();

            // PDF作成
            Document document = new Document();
            PdfWriter.getInstance(document, new FileOutputStream("chart_multipage.pdf"));
            document.open();

            // 1ページ目:グラフ画像
            Image chartImage = Image.getInstance(image, null);
            chartImage.scaleToFit(500, 300);
            document.add(chartImage);

            // 改ページ
            document.newPage();

            // 2ページ目:統計値表(簡易的にParagraphで出力)
            document.add(new Paragraph("=== 統計値 ==="));
            for (int i = 0; i < datasets.size(); i++) {
                Map<Integer, Integer> data = datasets.get(i);
                document.add(new Paragraph(labels.get(i) + " のデータ: " + data));
                int sum = data.values().stream().mapToInt(Integer::intValue).sum();
                double avg = sum / (double) data.size();
                document.add(new Paragraph("合計: " + sum + ", 平均: " + avg));
                document.add(new Paragraph("最大値: " + Collections.max(data.values()) +
                                           ", 最小値: " + Collections.min(data.values())));
                document.add(new Paragraph(" "));
            }

            document.close();
            System.out.println("chart_multipage.pdf に保存しました。");
        } catch (Exception e) {
            e.printStackTrace();
        }

        // GUI表示(確認用)
        JFrame frame = new JFrame("PDF出力用グラフ");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
    }
}
Java

✅ 実行結果

  • chart_multipage.pdf が生成されます
    • 1ページ目 → グラフ画像
    • 2ページ目 → 各データセットの統計値(合計・平均・最大・最小)

ポイント

  • document.newPage() でページを切り替え
  • グラフは Swing パネルを BufferedImage に描画して iText の Image に変換
  • 統計値は Paragraph で簡易的に出力(本格的には PdfPTable を使うと表形式にできる)

👉 これで「グラフ+統計値の複数ページPDF出力」が完成しました。

Java
スポンサーリンク
シェアする
@lifehackerをフォローする
スポンサーリンク
タイトルとURLをコピーしました