Itext7 end_page события вызываются, когда документ закрыт - PullRequest
0 голосов
/ 21 мая 2018

Я пытаюсь следовать примеру, приведенному в https://developers.itextpdf.com/examples/page-events/clone-page-events-headers-and-footers#2656-variableheader.java, для создания PDF-документа с переменным заголовком.Но события происходят не правильно.Вот код, который я протестировал с -

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».Но они должны показать «ФАКТОРЫ 2» для первой страницы, «ФАКТОРЫ 3» для второй страницы и «ФАКТОРЫ 4» для третьей страницы.Я не уверен, как это исправить.Есть предложения?

1 Ответ

0 голосов
/ 23 мая 2018

Как уже упоминалось в более раннем ответе События страницы iText 7 запускаются с некоторой задержкой - как правило, не до тех пор, пока документ не будет закрыт, хотя, как вы предполагаете в заголовке вопроса,но страница n + 1 может быть уже почти завершена до того, как будет обработано событие для страницы n .

Таким образом, для установки недостаточнозаголовок новой страницы как атрибут обработчика события, также необходимо указать обработчику события, когда начинать его использовать.Итак ...

Улучшенный обработчик

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

Этот улучшенный обработчик можно использовать так:

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

Результат - ожидаемый результат.

Вариант с несколькими элементами заголовка

Мы, вероятно, не хотим тратить так много страниц на такой маленький контент.В этом случае факторизации нескольких чисел должны помещаться на одной странице, и мы хотели бы, чтобы все они упоминались в заголовке.Это может быть достигнуто с использованием альтернативного прослушивателя событий, например:

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

. Сообщив прослушивателю событий сразу после рисования заголовка раздела для нового номера,номер будет указан в заголовке страницы, на которой напечатан этот заголовок раздела, в то время как фактическая факторизация может быть на следующей странице.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...