You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 19:54:14