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

使用说明

要运行此程序,您需要以下依赖项:

  1. iText 7 Core库 (用于PDF生成)
  2. 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>

程序功能

  1. 表格自定义

    • 添加/删除表格行
    • 编辑表格内容
    • 支持多列数据
  2. 图片插入

    • 添加多张图片
    • 自动调整图片大小
    • 保持图片宽高比
  3. PDF操作

    • 预览生成的PDF
    • 导出PDF文件
    • 自动打开生成的PDF
  4. 用户界面

    • 表格数据编辑区
    • PDF内容预览区
    • 操作按钮面板

使用步骤

  1. 在表格中编辑或添加图书数据
  2. 点击"添加图片"按钮插入图书封面
  3. 使用"预览PDF"查看效果
  4. 满意后点击"导出PDF"保存文件

程序会自动为表格添加样式,并根据评分值显示不同颜色,使生成的PDF更具可读性。

注意:实际使用中,您可能需要添加中文字体支持以正确显示中文内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/89453.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/89453.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/89453.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sklearn机器学习概述及API详细使用指南

一、机器学习与sklearn简介 机器学习是人工智能的一个分支&#xff0c;它通过算法让计算机从数据中学习规律&#xff0c;并基于这些规律做出预测或决策。scikit-learn&#xff08;简称sklearn&#xff09;是Python中最流行的机器学习库之一&#xff0c;它提供了各种监督学习和…

「日拱一码」015 机器学习常用库——scikit-learn

目录 数据预处理 数据标准化&#xff08;StandardScaler&#xff09; 数据归一化&#xff08;MinMaxScaler&#xff09; 数据离散化&#xff08;KBinsDiscretizer&#xff09; 缺失值处理&#xff08;SimpleImputer&#xff09; 特征选择 基于单变量特征选择&#xff08…

网络编程学习路线

C网络编程从零基础到精通的学习路线&#xff0c;每一步都和你的项目实际需求紧密结合&#xff0c;帮助你真正做到“学以致用”。 C网络编程学习路线&#xff08;结合FileHub项目&#xff09; 第一阶段&#xff1a;网络编程基础入门 1. 计算机网络基础 理解OSI七层模型、TCP/I…

NLP:文本张量表示方法

本文目录&#xff1a; 一、one-hot编码二、word2vec模型&#xff08;一&#xff09;概念1.CBOW(Continuous bag of words)模式2.skipgram模式:3.词向量的检索获取 &#xff08;二&#xff09;word2vec的训练和使用1. 获取训练数据2.查看原始数据3.原始数据处理&#xff0c;并查…

高阶数据结构------并查集

并查集 在一些应用问题中&#xff0c;需要将n个不同的元素划分成一些不相交的集合。开始时&#xff0c;每个元素自成一个集合&#xff0c;然后按照一定的规律将归于同一组的元素集合合并。在此过程中要反复用到查询某一个元素归属于哪一个集合的运算。适合于描述这类问题的抽象…

OWASP Top 10 是什么?

OWASP&#xff08;Open Web Application Security Project&#xff0c;开放Web应用安全项目&#xff09;是一个致力于提高软件安全性的国际非营利组织。其发布的 ​OWASP Top 10​ 是最具影响力的Web应用安全风险清单&#xff0c;每3-4年更新一次&#xff0c;帮助开发人员、安全…

如何在IIS上部署net系统(安装iis参考上一篇)

1.对后端项目打包&#xff0c;我使用的时rider 2.打包前端 npm run build 3.在iis上部署 网站-添加网站 4.选择之前打包的后端文件&#xff0c;设置端口 5.安装对应net环境插件&#xff1a;主要是runtime和sdk插件以及dotnet-hosting-2.2.0-win&#xff0c;具体版本看自己项…

Docker可视化管理工具Portainer安装部署

1、安装Portainer 编写docker compose文件&#xff0c;使用docker compose文件完成Portainer的安装&#xff0c;首先需要在服务器上编写的名为portainer.yaml的文件&#xff0c;内容如下&#xff1a; [rootserver ~]# cat portainer.yaml services: portainer: image:…

ai之RAG本地知识库--基于OCR和文本解析器的新一代RAG引擎:RAGFlow 认识和源码剖析

目录标题 RAG本地知识库问答——基于OCR和文本解析器的新一代RAG引擎&#xff1a;RAGFlow 认识和源码剖析RAGflow 主要功能&#xff1a; 一、RAGflow 简介1.1 允许用户上传并管理自己的文档(文档类型可以是任意类型)1.2 RAGFlow的4个特色1.2.1 AI 模型的智能文档处理系统1.2.2 …

[面试] 手写题-new

function mynew(Func, ...args) {// 1.创建一个空对象const obj {}// 2.新对象隐式原型指向构造函数的显式原型obj.__proto__ Func.prototype// 3.将构建函数的this指向新对象let result Func.apply(obj, args)// 4.返回objreturn result instanceof Object ? result : obj…

设计模式精讲 Day 20:状态模式(State Pattern)

【设计模式精讲 Day 20】状态模式&#xff08;State Pattern&#xff09; 文章标签 设计模式, 状态模式, Java开发, 面向对象设计, 软件架构, 设计模式实战, Java应用开发 文章简述 状态模式是行为型设计模式中的重要一员&#xff0c;用于管理对象在不同状态下的行为变化。在…

桥岛隧大型工程 3D 可视化监测平台

深中通道作为“桥、岛、隧、水下互通”一体化跨海集群工程&#xff0c;其复杂结构带来高强度监测难题。借助图扑软件 HT 实现深中通道的建设与运营的数字化升级&#xff0c;为交通基建行业迈向高效、智能的未来提供了有力支撑。 图扑自主研发的 HT for Web 产品搭建深中通道-桥…

基于SpringBoot和Leaflet的区域冲突可视化系统(2025企业级实战方案)

摘要 在全球地缘冲突与应急事件频发的2025年&#xff0c;区域态势可视化系统成为政府及企业的决策刚需。本文提出基于​​SpringBoot 3.2​​后端与​​Leaflet 1.9.5​​前端的冲突可视化解决方案&#xff0c;融合多源异构数据&#xff08;卫星影像、舆情热力、设施状态&…

[密码学实战]国密TLCP协议报文解析代码实现(三十)

[密码学实战]国密TLCP协议报文解析代码实现(三十) 本文将深入解析国密TLCP协议报文结构,提供完整的Java实现代码,帮助开发者理解TLCP协议在国密环境下的通信机制和安全性设计。 一、国密TLCP协议概述 TLCP(Transport Layer Cryptographic Protocol)是基于国密算法(SM2/…

[Python] -基础篇5-玩转Python内置数据结构:列表、元组、字典与集合

Python 是一门以简洁优雅著称的编程语言,其中内置的数据结构为日常编程提供了强大支持。本文将系统介绍 Python 中四大核心数据结构:列表(list)、元组(tuple)、字典(dict)与集合(set),并配以实用示例,帮助读者全面掌握其用法及适用场景。 一、列表(List):可变序…

技术突破与落地应用:端到端 2.0 时代辅助驾驶TOP10 论文深度拆解系列【第八篇(排名不分先后)】

HiP-AD: Hierarchical and Multi-Granularity Planning with Deformable Attention for Autonomous Driving in a Single Decoder GitHub地址&#xff1a;​https://github.com/nullmax-vision/HiP-AD​ 在自动驾驶技术飞速发展的今天&#xff0c;端到端自动驾驶&#xff08;E…

transformer位置编码研究相关的综述、论文

一、权威综述 《利用位置编码实现长度外推》 &#xff08;腾讯云开发者社区, 2024&#xff09; 系统分析绝对/相对位置编码&#xff08;APE/RPE&#xff09;在长序列外推中的技术演进&#xff0c;涵盖RoPE、Alibi、Xpos等优化方案&#xff0c;讨论位置插值、NTK-aware缩放等扩展…

垂直领域AI智能体开发指南:用Bright Data MCP接入智能体攻克数据难关

垂直领域AI智能体开发指南&#xff1a;用Bright Data MCP接入智能体攻克数据难关 一、智能体时代的数据困局1.1 AI智能体的爆发式增长1.2 开发者遭遇的"数据瓶颈" 二、Bright Data MCP&#xff1a;智能体的数据引擎2.1 重新定义数据获取方式2.2 支持的核心场景2.3 四…

Stable Diffusion 项目实战落地:从0到1 掌握ControlNet 第三篇: 打造光影字形的创意秘技-文字与自然共舞

上一篇,我们一起玩转了 野外光影字,是不是被那种自然和光影交织的效果惊艳到啦? 如果你错过了那篇文章,别担心,赶紧点这里补课:Stable Diffusion 项目实战落地:从0到1 掌握ControlNet:打造光影文字 第二篇 - 野外光影字。 今天,我们将一起做一个 生成的嵌入式文字【…

CppCon 2018 学习:Feather: A Modern C++ Web Development Framework

你这段内容罗列的是 Web 开发中的几个基础概念和组成模块&#xff0c;下面我逐一用中文进行解释&#xff0c;并理清它们之间的关系&#xff1a; 基础概念说明 1. HTTP Server&#xff08;HTTP服务器&#xff09; 是一个监听 HTTP 请求并返回响应的程序。主要功能&#xff1a…