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

使用iTextPDF生成PDF时跨页表格内容褪色问题求助

问题:iTextPDF生成PDF时跨页表格内容颜色变淡

使用iTextPDF生成PDF时,表格内容延伸到下一页后显示颜色变淡。生成4页PDF时,第1页和第4页显示正常,但第2、3页的表格内容明显褪色。

使用的是单页PDF模板,需要复制模板页面,事件监听器无法自动复制到第二页,因此手动复制了第一页,后续监听器可正常工作,但仍存在表格内容褪色问题。

相关代码

public class PdfGenerator {
    public static void main(String[] args) throws IOException {

        ClassPathResource templateResource = new ClassPathResource("RandomTemplate.pdf");
        File pdfFile = new File(templateResource.getFile().getAbsolutePath());

        CustomEventHandler eventHandler = null;

        try (PdfReader pdfReader = new PdfReader(pdfFile);
        ) {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            PdfWriter pdfWriter = new PdfWriter(outputStream);
            PdfDocument targetDocument = new PdfDocument(pdfReader, pdfWriter);

            PdfReader pdfReader2 = new PdfReader(pdfFile);
            PdfDocument sourceDocument = new PdfDocument(pdfReader2);

            eventHandler = new CustomEventHandler(sourceDocument);
            targetDocument.addEventHandler(PdfDocumentEvent.END_PAGE, eventHandler);

            Document document = new Document(targetDocument);
            document.setMargins(95, 24, 100, 24);

            sourceDocument.copyPagesTo(1, 1, targetDocument);

            for (int i = 0; i < 3; i++) {
                Table table = new Table(4);

                table.addHeaderCell(new Cell(1, 4).add(new Paragraph("Random Header Title")).setBold().setPaddingLeft(5).setBorderLeft(new SolidBorder(3)));
                table.addHeaderCell(new Cell().add(new Paragraph("RANDOM DATE")).setBold().setPaddingLeft(5).setBorderRight(Border.NO_BORDER).setBorderLeft(Border.NO_BORDER).setBorderBottom(Border.NO_BORDER));
                table.addHeaderCell(new Cell().add(new Paragraph("RANDOM MEASUREMENT")).setBold().setPaddingLeft(5).setBorderRight(Border.NO_BORDER).setBorderLeft(Border.NO_BORDER).setBorderBottom(Border.NO_BORDER));
                table.addHeaderCell(new Cell().add(new Paragraph("RANDOM PERCENTILE")).setBold().setPaddingLeft(5).setBorderRight(Border.NO_BORDER).setBorderLeft(Border.NO_BORDER).setBorderBottom(Border.NO_BORDER)).setFontSize(7);
                table.addHeaderCell(new Cell().add(new Paragraph("RANDOM SCORE")).setBold().setPaddingLeft(5).setBorderRight(Border.NO_BORDER).setBorderLeft(Border.NO_BORDER).setBorderBottom(Border.NO_BORDER));

                for (int j = 0; j < 50; j++) {
                    table.addCell(new Cell().add(new Paragraph("dd/mm/yyyy")).setPaddingLeft(5).setBorderRight(Border.NO_BORDER).setBorderLeft(Border.NO_BORDER).setBorderTop(Border.NO_BORDER));
                    table.addCell(new Cell().add(new Paragraph(String.valueOf(j + 1))).setPaddingLeft(5).setBorderRight(Border.NO_BORDER).setBorderLeft(Border.NO_BORDER).setBorderTop(Border.NO_BORDER));
                    table.addCell(new Cell().add(new Paragraph("#.#%")).setPaddingLeft(5).setBorderRight(Border.NO_BORDER).setBorderLeft(Border.NO_BORDER).setBorderTop(Border.NO_BORDER)).setFontSize(8);
                    table.addCell(new Cell().add(new Paragraph("#.##")).setPaddingLeft(5).setBorderRight(Border.NO_BORDER).setBorderLeft(Border.NO_BORDER).setBorderTop(Border.NO_BORDER));
                }

                table.setBorder(new SolidBorder(1));
                table.setWidth(767);
                table.setMarginTop(20);
                document.add(table);

            }

            targetDocument.removeEventHandler(PdfDocumentEvent.END_PAGE, eventHandler);
            document.close();
            targetDocument.close();

            byte[] finalPdfBytes = outputStream.toByteArray();

            FileOutputStream fileOutputStream = new FileOutputStream("FinalRandomOutput.pdf");
            fileOutputStream.write(finalPdfBytes);
            fileOutputStream.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static class CustomEventHandler implements IEventHandler {
        private final PdfDocument sourceDocument;

        public CustomEventHandler(PdfDocument sourceDocument) {
            this.sourceDocument = sourceDocument;
        }

        @Override
        public void handleEvent(Event event) {
            System.out.println("Event Triggered");
            PdfDocumentEvent documentEvent = (PdfDocumentEvent) event;
            PdfDocument pdfDocument = documentEvent.getDocument();
            PdfPage originalPage = sourceDocument.getPage(1);
            pdfDocument.addPage(originalPage.copyTo(pdfDocument));
        }
    }
}

问题原因分析

你的CustomEventHandler在END_PAGE事件触发时,直接将模板页面添加到目标文档末尾,而不是为新页面设置模板背景。这会导致:

  1. 当表格内容触发分页时,iText会自动创建新的空白页,之后事件监听器又添加了一个模板页,相当于在表格所在的空白页后插入模板页。
  2. 表格内容被渲染在无模板的空白页上,和有模板背景的第1、4页形成视觉对比,看起来颜色变淡。

解决方案

正确的做法是在新页面创建时,将模板页面的内容作为背景绘制到当前页面,而不是直接添加新的模板页。

修改后的事件处理器

static class CustomEventHandler implements IEventHandler {
    private final PdfDocument sourceDocument;

    public CustomEventHandler(PdfDocument sourceDocument) {
        this.sourceDocument = sourceDocument;
    }

    @Override
    public void handleEvent(Event event) {
        PdfDocumentEvent documentEvent = (PdfDocumentEvent) event;
        PdfDocument pdfDocument = documentEvent.getDocument();
        PdfPage currentPage = documentEvent.getPage();
        PdfPage originalPage = sourceDocument.getPage(1);

        // 获取当前页面的底层画布,将模板内容作为背景绘制
        PdfCanvas canvas = new PdfCanvas(currentPage.newContentStreamBefore(), currentPage.getResources(), pdfDocument);
        // 复制模板页面内容到当前页面
        originalPage.copyAsFormXObject(pdfDocument).copyToCanvas(canvas, new AffineTransform());
    }
}

主方法对应修改

// 将事件监听改为START_PAGE,在页面创建时就设置背景
targetDocument.addEventHandler(PdfDocumentEvent.START_PAGE, eventHandler);

// 移除手动复制模板页的代码,START_PAGE事件会自动处理所有页面
// sourceDocument.copyPagesTo(1, 1, targetDocument);

// 直接创建文档并添加表格内容
Document document = new Document(targetDocument);
document.setMargins(95, 24, 100, 24);

// 表格添加逻辑保持不变
for (int i = 0; i < 3; i++) {
    // ...原表格代码
}

额外注意事项

  • 确保模板页面尺寸和目标文档页面尺寸一致,避免背景错位。
  • 移除原END_PAGE事件的页面添加逻辑,避免重复创建页面。
  • 文档关闭只需调用document.close()即可,它会自动关联关闭PdfDocument。

这样修改后,所有页面都会自动应用模板背景,表格内容无论在第几页都会和背景正确叠加,不会出现颜色变淡的问题。

内容的提问来源于stack exchange,提问作者user26321118

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 05:50:57