Java 导出PDF 1、内容可以插入自定义表格 2、内容插入图片
Java PDF导出工具:自定义表格与图片插入
下面我将实现一个Java PDF导出工具,支持插入自定义表格和图片的功能。这个解决方案使用iText 7库,提供了一个直观的用户界面,可以预览生成的PDF内容。
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.UnitValue;public class PDFExporter extends JFrame {private JTable table;private DefaultTableModel tableModel;private JTextArea previewArea;private List<String> imagePaths = new ArrayList<>();private PdfFont font;private PdfFont titleFont;public PDFExporter() {super("PDF导出工具 - 支持自定义表格与图片插入");setSize(900, 700);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setLocationRelativeTo(null);initFonts();initUI();}private void initFonts() {try {// 创建字体(实际应用中应使用支持中文的字体文件)font = PdfFontFactory.createFont();titleFont = PdfFontFactory.createFont(PdfFontFactory.HELVETICA_BOLD);} catch (Exception e) {e.printStackTrace();font = PdfFontFactory.createFont(PdfFontFactory.COURIER);titleFont = PdfFontFactory.createFont(PdfFontFactory.COURIER_BOLD);}}private void initUI() {// 创建主面板JPanel mainPanel = new JPanel(new BorderLayout(10, 10));mainPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));// 创建顶部面板JPanel topPanel = new JPanel(new BorderLayout(10, 10));// 表格模型String[] columns = {"书名", "作者", "价格 (¥)", "出版年份", "评分"};tableModel = new DefaultTableModel(columns, 0);table = new JTable(tableModel);table.setRowHeight(30);table.setFont(new Font("微软雅黑", Font.PLAIN, 14));// 添加示例数据addSampleData();JScrollPane tableScroll = new JScrollPane(table);tableScroll.setBorder(BorderFactory.createTitledBorder("自定义表格数据"));topPanel.add(tableScroll, BorderLayout.CENTER);// 表格操作按钮JPanel tableButtonPanel = new JPanel(new GridLayout(5, 1, 5, 5));JButton addRowBtn = new JButton("添加行");JButton deleteRowBtn = new JButton("删除行");JButton addImageBtn = new JButton("添加图片");JButton previewBtn = new JButton("预览PDF");JButton exportBtn = new JButton("导出PDF");addRowBtn.addActionListener(e -> tableModel.addRow(new Object[]{"", "", "", "", ""}));deleteRowBtn.addActionListener(e -> {int row = table.getSelectedRow();if (row != -1) {tableModel.removeRow(row);}});addImageBtn.addActionListener(e -> addImage());previewBtn.addActionListener(e -> previewPDF());exportBtn.addActionListener(e -> exportPDF());tableButtonPanel.add(addRowBtn);tableButtonPanel.add(deleteRowBtn);tableButtonPanel.add(addImageBtn);tableButtonPanel.add(previewBtn);tableButtonPanel.add(exportBtn);topPanel.add(tableButtonPanel, BorderLayout.EAST);// 预览区域previewArea = new JTextArea();previewArea.setFont(new Font("等线", Font.PLAIN, 14));previewArea.setEditable(false);previewArea.setBackground(new Color(240, 240, 240));previewArea.setBorder(BorderFactory.createTitledBorder("PDF预览内容"));JScrollPane previewScroll = new JScrollPane(previewArea);previewScroll.setPreferredSize(new Dimension(0, 200));// 添加组件到主面板mainPanel.add(topPanel, BorderLayout.CENTER);mainPanel.add(previewScroll, BorderLayout.SOUTH);add(mainPanel);// 状态栏JLabel statusBar = new JLabel("就绪 | 添加表格数据并插入图片,然后导出PDF");statusBar.setBorder(BorderFactory.createEtchedBorder());add(statusBar, BorderLayout.SOUTH);updatePreview();}private void addSampleData() {Object[][] data = {{"Java核心技术", "Cay S. Horstmann", "128.50", "2022", "4.8"},{"Effective Java", "Joshua Bloch", "99.80", "2018", "4.9"},{"深入理解Java虚拟机", "周志明", "119.00", "2019", "4.7"},{"Spring实战", "Craig Walls", "89.90", "2020", "4.6"},{"Python编程:从入门到实践", "Eric Matthes", "75.00", "2021", "4.7"}};for (Object[] row : data) {tableModel.addRow(row);}}private void addImage() {JFileChooser fileChooser = new JFileChooser();fileChooser.setDialogTitle("选择要插入的图片");fileChooser.setMultiSelectionEnabled(true);int result = fileChooser.showOpenDialog(this);if (result == JFileChooser.APPROVE_OPTION) {for (File file : fileChooser.getSelectedFiles()) {imagePaths.add(file.getAbsolutePath());}updatePreview();JOptionPane.showMessageDialog(this, "已添加 " + fileChooser.getSelectedFiles().length + " 张图片", "添加图片", JOptionPane.INFORMATION_MESSAGE);}}private void updatePreview() {StringBuilder sb = new StringBuilder();sb.append("PDF 内容预览:\n");sb.append("----------------------------------------\n");sb.append("标题: 图书清单报告\n\n");sb.append("表格数据 (").append(tableModel.getRowCount()).append(" 行):\n");for (int col = 0; col < tableModel.getColumnCount(); col++) {sb.append(String.format("%-20s", tableModel.getColumnName(col)));}sb.append("\n");for (int row = 0; row < tableModel.getRowCount(); row++) {for (int col = 0; col < tableModel.getColumnCount(); col++) {Object value = tableModel.getValueAt(row, col);sb.append(String.format("%-20s", value != null ? value.toString() : ""));}sb.append("\n");}sb.append("\n图片列表 (").append(imagePaths.size()).append(" 张):\n");for (String path : imagePaths) {sb.append("• ").append(new File(path).getName()).append("\n");}previewArea.setText(sb.toString());}private void previewPDF() {try {File tempFile = File.createTempFile("pdf_preview", ".pdf");createPDF(tempFile.getAbsolutePath());if (Desktop.isDesktopSupported()) {Desktop.getDesktop().open(tempFile);} else {JOptionPane.showMessageDialog(this, "PDF预览已生成: " + tempFile.getAbsolutePath(), "预览生成成功", JOptionPane.INFORMATION_MESSAGE);}} catch (Exception ex) {ex.printStackTrace();JOptionPane.showMessageDialog(this, "生成预览时出错: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);}}private void exportPDF() {JFileChooser fileChooser = new JFileChooser();fileChooser.setDialogTitle("保存PDF文件");fileChooser.setSelectedFile(new File("图书清单报告.pdf"));int result = fileChooser.showSaveDialog(this);if (result == JFileChooser.APPROVE_OPTION) {File file = fileChooser.getSelectedFile();String filePath = file.getAbsolutePath();if (!filePath.toLowerCase().endsWith(".pdf")) {filePath += ".pdf";}try {createPDF(filePath);JOptionPane.showMessageDialog(this, "PDF导出成功: " + filePath, "导出成功", JOptionPane.INFORMATION_MESSAGE);if (Desktop.isDesktopSupported()) {Desktop.getDesktop().open(new File(filePath));}} catch (Exception ex) {ex.printStackTrace();JOptionPane.showMessageDialog(this, "导出PDF时出错: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);}}}private void createPDF(String filePath) throws Exception {try (PdfWriter writer = new PdfWriter(filePath);PdfDocument pdf = new PdfDocument(writer);Document document = new Document(pdf)) {// 设置文档属性document.setMargins(50, 50, 50, 50);// 添加标题Paragraph title = new Paragraph("图书清单报告").setFont(titleFont).setFontSize(24).setTextAlignment(TextAlignment.CENTER).setFontColor(ColorConstants.DARK_GRAY).setMarginBottom(20);document.add(title);// 添加副标题Paragraph subtitle = new Paragraph("自定义表格与图片展示").setFont(font).setFontSize(16).setTextAlignment(TextAlignment.CENTER).setFontColor(ColorConstants.GRAY).setMarginBottom(30);document.add(subtitle);// 添加表格addTableToDocument(document);// 添加图片addImagesToDocument(document);// 添加页脚Paragraph footer = new Paragraph("生成时间: " + new java.util.Date()).setFont(font).setFontSize(10).setTextAlignment(TextAlignment.CENTER).setFontColor(ColorConstants.LIGHT_GRAY).setMarginTop(30);document.add(footer);}}private void addTableToDocument(Document document) {// 创建表格float[] columnWidths = {3, 2, 1, 1, 1};Table pdfTable = new Table(UnitValue.createPercentArray(columnWidths));pdfTable.setWidth(UnitValue.createPercentValue(100));pdfTable.setMarginBottom(30);// 添加表头for (int col = 0; col < tableModel.getColumnCount(); col++) {Cell headerCell = new Cell().add(new Paragraph(tableModel.getColumnName(col)).setFont(titleFont).setFontSize(12).setBackgroundColor(new com.itextpdf.kernel.color.Color(230, 230, 230)).setTextAlignment(TextAlignment.CENTER);pdfTable.addHeaderCell(headerCell);}// 添加表格数据for (int row = 0; row < tableModel.getRowCount(); row++) {for (int col = 0; col < tableModel.getColumnCount(); col++) {Object value = tableModel.getValueAt(row, col);String text = value != null ? value.toString() : "";Cell dataCell = new Cell().add(new Paragraph(text)).setFont(font).setFontSize(11);// 设置特殊列的样式if (col == 2) { // 价格列dataCell.setTextAlignment(TextAlignment.RIGHT);} else if (col == 4) { // 评分列try {double rating = Double.parseDouble(text);if (rating >= 4.5) {dataCell.setFontColor(ColorConstants.GREEN);} else if (rating >= 4.0) {dataCell.setFontColor(ColorConstants.BLUE);} else {dataCell.setFontColor(ColorConstants.ORANGE);}} catch (NumberFormatException e) {// 忽略格式错误}dataCell.setTextAlignment(TextAlignment.CENTER);} else {dataCell.setTextAlignment(TextAlignment.LEFT);}pdfTable.addCell(dataCell);}}document.add(pdfTable);}private void addImagesToDocument(Document document) throws Exception {if (imagePaths.isEmpty()) return;// 添加图片标题Paragraph imageTitle = new Paragraph("图书封面").setFont(titleFont).setFontSize(16).setMarginBottom(15);document.add(imageTitle);// 添加图片for (String path : imagePaths) {if (!Files.exists(Paths.get(path))) continue;try {ImageData imageData = ImageDataFactory.create(path);Image pdfImage = new Image(imageData);// 调整图片大小(最大宽度400px,保持宽高比)float width = pdfImage.getImageWidth();float height = pdfImage.getImageHeight();float maxWidth = 400;if (width > maxWidth) {float ratio = maxWidth / width;pdfImage.scale(ratio, ratio);}// 居中显示pdfImage.setHorizontalAlignment(com.itextpdf.layout.property.HorizontalAlignment.CENTER);pdfImage.setMarginBottom(20);document.add(pdfImage);} catch (Exception e) {System.err.println("无法加载图片: " + path);e.printStackTrace();}}}public static void main(String[] args) {SwingUtilities.invokeLater(() -> {try {UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());} catch (Exception e) {e.printStackTrace();}PDFExporter exporter = new PDFExporter();exporter.setVisible(true);});}
}
使用说明
要运行此程序,您需要以下依赖项:
- iText 7 Core库 (用于PDF生成)
- Java Swing (用于GUI)
Maven依赖配置
<dependencies><!-- iText 7 Core --><dependency><groupId>com.itextpdf</groupId><artifactId>itext7-core</artifactId><version>7.2.5</version><type>pom</type></dependency><!-- 其他必要的依赖项 -->
</dependencies>
程序功能
-
表格自定义:
- 添加/删除表格行
- 编辑表格内容
- 支持多列数据
-
图片插入:
- 添加多张图片
- 自动调整图片大小
- 保持图片宽高比
-
PDF操作:
- 预览生成的PDF
- 导出PDF文件
- 自动打开生成的PDF
-
用户界面:
- 表格数据编辑区
- PDF内容预览区
- 操作按钮面板
使用步骤
- 在表格中编辑或添加图书数据
- 点击"添加图片"按钮插入图书封面
- 使用"预览PDF"查看效果
- 满意后点击"导出PDF"保存文件
程序会自动为表格添加样式,并根据评分值显示不同颜色,使生成的PDF更具可读性。
注意:实际使用中,您可能需要添加中文字体支持以正确显示中文内容。