Java GUI通过JFileChooser实现PdfAcroForm PDF自定义保存
实现方案
核心修改逻辑如下:
- 删除原有代码中写死输出路径的
DEST常量,以及类初始化时就创建的绑定固定路径的PdfDocument实例,避免程序启动就占用文件句柄 - 在保存按钮的点击事件中初始化
JFileChooser,配置专属PDF文件过滤器,仅允许选择/保存为.pdf格式,默认打开原src/pdf目录 - 增加用户操作判断:如果用户点击取消按钮直接终止流程,不执行后续生成逻辑
- 自动补全文件名后缀:即使用户输入文件名时没加
.pdf,程序也会自动补上,保证输出格式正确 - 增加重复文件覆盖提示、异常捕获提示,避免程序无响应崩溃
修改后可直接运行的代码如下:
import javax.swing.*; import javax.swing.filechooser.FileFilter; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Map; // 此处保留原有iText相关包导入 public class PdfGenerator extends JFrame implements ActionListener { public static final String SRC = "src/pdf/invoice.pdf"; public PdfGenerator() { // 原有GUI组件初始化、布局代码保留 btnSave.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // 初始化文件保存选择器 JFileChooser fileChooser = new JFileChooser(); // 默认打开原pdf存储目录 fileChooser.setCurrentDirectory(new File("src/pdf")); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); // 隐藏"所有文件"选项,仅保留PDF格式过滤器 fileChooser.setAcceptAllFileFilterUsed(false); fileChooser.addChoosableFileFilter(new FileFilter() { @Override public boolean accept(File f) { if (f.isDirectory()) { return true; } return f.getName().toLowerCase().endsWith(".pdf"); } @Override public String getDescription() { return "PDF文件 (*.pdf)"; } }); // 弹出保存对话框,判断用户选择 int userSelection = fileChooser.showSaveDialog(PdfGenerator.this); if (userSelection != JFileChooser.APPROVE_OPTION) { // 用户点击取消,直接终止流程 return; } // 获取用户选择的输出文件,自动补全.pdf后缀 File outFile = fileChooser.getSelectedFile(); if (!outFile.getName().toLowerCase().endsWith(".pdf")) { outFile = new File(outFile.getParentFile(), outFile.getName() + ".pdf"); } // 重复文件覆盖确认,不需要可删除这段逻辑 if (outFile.exists()) { int confirmRes = JOptionPane.showConfirmDialog(PdfGenerator.this, "选中位置已存在同名文件,是否覆盖?", "覆盖确认", JOptionPane.YES_NO_OPTION); if (confirmRes != JOptionPane.YES_OPTION) { return; } } // 选定路径后再初始化PDF文档,用try-with-resources自动释放资源 try (PdfDocument pdf = new PdfDocument(new PdfReader(SRC), new PdfWriter(outFile))) { PdfAcroForm form = PdfAcroForm.getAcroForm(pdf, true); Map<String, PdfFormField> fields = form.getFormFields(); fields.get("nr_invoice").setValue(invoice.getText()); fields.get("client").setValue(cl_name.getText()); fields.get("service").setValue(description.getText()); fields.get("price").setValue(amount.getText()); fields.get("quantity").setValue(quantity.getText()); fields.get("tax").setValue(tax_amount.getText()); fields.get("tot").setValue(total_price.getText()); form.flattenFields(); JOptionPane.showMessageDialog(PdfGenerator.this, "发票保存成功", "操作提示", JOptionPane.INFORMATION_MESSAGE); } catch (FileNotFoundException ex) { JOptionPane.showMessageDialog(PdfGenerator.this, "所选路径无写入权限,请重新选择", "保存失败", JOptionPane.ERROR_MESSAGE); } catch (IOException ex) { JOptionPane.showMessageDialog(PdfGenerator.this, "PDF生成异常:" + ex.getMessage(), "保存失败", JOptionPane.ERROR_MESSAGE); } } }); } @Override public void actionPerformed(ActionEvent e) { // 原有其他组件事件逻辑保留 } }
注意:如果把
PdfDocument实例定义在事件监听外部,程序启动时就会锁定固定路径的文件,不仅无法实现动态路径选择,还可能引发文件被占用无法修改、删除的问题,必须将PDF初始化逻辑移到用户确认保存路径之后。
内容的提问来源于stack exchange,提问作者Count
相关产品推荐
相关产品推荐

