文档关闭时调用itext7 end_page事件 [英] itext7 end_page events are called when document is closed

查看:403
本文介绍了文档关闭时调用itext7 end_page事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试按照 https://developers.itextpdf.com/examples/page-events/clone-page-events-headers-and-footers#2656-variableheader.java 创建PDF文档带有变量头。但是这些事件没有被正确解雇。以下是我测试过的代码 -

I am trying to follow the example given in https://developers.itextpdf.com/examples/page-events/clone-page-events-headers-and-footers#2656-variableheader.java to create a PDF document with variable header. But the events are not fired correctly. Here is the code I have tested with -

class Program
{
    public static String DEST = "test.pdf";
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");

        manipulatePdf(DEST);
    }


    public static List<int> getFactors(int n)
    {
        List<int> factors = new List<int>();
        for (int i = 2; i <= n; i++)
        {
            while (n % i == 0)
            {
                factors.Add(i);
                n /= i;
            }
        }
        return factors;
    }

    protected static void manipulatePdf(String dest)
    {
        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(DEST));
        Document doc = new Document(pdfDoc, PageSize.A4, true);
        VariableHeaderEventHandler handler = new VariableHeaderEventHandler();
        pdfDoc.AddEventHandler(PdfDocumentEvent.END_PAGE, handler);
        List<int> factors;
        for (int i = 2; i < 4; i++)
        {
            factors = getFactors(i);
            if (factors.Count == 1)
            {
                doc.Add(new Paragraph("This is a prime number!"));
            }
            foreach (int factor in factors)
            {
                doc.Add(new Paragraph("Factor: " + factor));
            }

            handler.setHeader(String.Format("THE FACTORS OF {0}", i));
            if (300 != i)
            {
                doc.Add(new AreaBreak());
            }
        }
        doc.Close();
    }


    protected class VariableHeaderEventHandler : IEventHandler
    {
        protected String header;

        public void setHeader(String header)
        {
            this.header = header;
        }

        public void HandleEvent(Event @event)
        {
            PdfDocumentEvent documentEvent = (PdfDocumentEvent)@event;
            try
            {
                new PdfCanvas(documentEvent.GetPage())
                        .BeginText()
                        .SetFontAndSize(PdfFontFactory.CreateFont(StandardFonts.HELVETICA), 12)
                        .MoveText(450, 806)
                        .ShowText(header)
                        .EndText()
                        .Stroke();
            }
            catch (IOException e)
            {
            }
        }
    }
}

如果我运行此代码,则所有页面都显示标题为3的因素。但他们应该为第一页的第一页3的因素和第三页的4的因素显示2的因素。我不知道如何解决它。有什么建议吗?

If I run this code, all pages show header as "THE FACTORS OF 3". But they should show "THE FACTORS OF 2" for first page "THE FACTORS OF 3" for second page and "THE FACTORS OF 4" for third page. I am not sure how to fix it. Any suggestions?

推荐答案

正如之前的回答 iText 7页面事件会有一些延迟触发 - 通常不会在文档关闭之前,正如您在问题标题中所假设的那样,但页面 n在处理页面 n 的事件之前,+1 确实已经接近完成。

As already mentioned in an earlier answer iText 7 page events are triggered with some delay - generally not until the document is closed, though, as you assume in your question title, but page n+1 may indeed already be nearly finished before the event for page n is processed.

因此,它不足以将新页眉设置为事件处理程序的属性,还必须告诉事件处理程序何时开始使用它。所以......

Thus, it does not suffice to set the new page header as attribute of the event handler, one also has to tell the event handler when to start using it. So ...

protected class ImprovedVariableHeaderEventHandler : IEventHandler
{
    Dictionary<PdfPage, String> headers = new Dictionary<PdfPage, string>();
    protected String header = "";

    public void setHeaderFor(String header, PdfPage page)
    {
        headers[page] = header;
    }

    public void HandleEvent(Event @event)
    {
        PdfDocumentEvent documentEvent = (PdfDocumentEvent)@event;
        PdfPage page = documentEvent.GetPage();
        if (headers.ContainsKey(page))
        {
            header = headers[page];
            headers.Remove(page);
        }
        new PdfCanvas(page)
                .BeginText()
                .SetFontAndSize(PdfFontFactory.CreateFont(StandardFonts.HELVETICA), 12)
                .MoveText(450, 806)
                .ShowText(header)
                .EndText()
                .Stroke();
    }
}

这个改进的处理程序可以像这样使用:

This improved handler can be used like this:

PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc, PageSize.A4, true);
ImprovedVariableHeaderEventHandler handler = new ImprovedVariableHeaderEventHandler();
pdfDoc.AddEventHandler(PdfDocumentEvent.END_PAGE, handler);
List<int> factors;
for (int i = 2; i < 40; i++)
{
    if (2 != i)
    {
        doc.Add(new AreaBreak());
    }

    factors = getFactors(i);
    if (factors.Count == 1)
    {
        doc.Add(new Paragraph("This is a prime number!"));
    }
    foreach (int factor in factors)
    {
        doc.Add(new Paragraph("Factor: " + factor));
    }

    handler.setHeaderFor(String.Format("THE FACTORS OF {0}", i), pdfDoc.GetLastPage());
}
doc.Close();

结果是您预期的输出。

我们可能不希望为这么少的内容浪费这么多页面。在这种情况下,多个数字的因子分解应该适合单个页面,我们希望在标题中提到所有这些因素。这可以使用这样的替代事件监听器来实现:

We probably don't want to waste so many pages for so little content. In that case the factorizations of multiple numbers should fit on a single page and we would like to have all of them mentioned in the header. That can be achieved using an alternative event listener like this:

protected class ImprovedVariableHeaderEventHandlerAlt : IEventHandler
{
    Dictionary<PdfPage, String> headers = new Dictionary<PdfPage, string>();
    protected String header = "";

    public void addHeaderDetailFor(string header, PdfPage page)
    {
        if (headers.ContainsKey(page))
            headers[page] += ", " + header;
        else
            headers[page] = header;
    }

    public void HandleEvent(Event @event)
    {
        PdfDocumentEvent documentEvent = (PdfDocumentEvent)@event;
        PdfPage page = documentEvent.GetPage();
        if (headers.ContainsKey(page))
        {
            header = String.Format("THE FACTORS OF {0}", headers[page]);
            headers.Remove(page);
        }
        new PdfCanvas(page)
                .BeginText()
                .SetFontAndSize(PdfFontFactory.CreateFont(StandardFonts.HELVETICA), 12)
                .MoveText(150, 806)
                .ShowText(header)
                .EndText()
                .Stroke();
    }
}

使用此代码:

PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc, PageSize.A4, true);
ImprovedVariableHeaderEventHandlerAlt handler = new ImprovedVariableHeaderEventHandlerAlt();
pdfDoc.AddEventHandler(PdfDocumentEvent.END_PAGE, handler);
List<int> factors;
for (int i = 2; i < 40; i++)
{
    doc.Add(new Paragraph(String.Format("The factors of {0}", i)).SetBold());
    handler.addHeaderDetailFor(i.ToString(), pdfDoc.GetLastPage());

    factors = getFactors(i);
    if (factors.Count == 1)
    {
        doc.Add(new Paragraph("This is a prime number!"));
    }
    foreach (int factor in factors)
    {
        doc.Add(new Paragraph("Factor: " + factor));
    }
}
doc.Close();

通过在绘制新标题的节标题后立即通知事件监听器,将提及该数字在打印此节标题的页面的页眉中,实际的分解可能在下一页上。

By informing the event listener right after drawing the section header for a new number, the number will be mentioned in the page header of the page on which this section header is printed while the actual factorization might be on the following page.

这篇关于文档关闭时调用itext7 end_page事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆