Переключаться между ColumnDocumentRenderer и DocumentRenderer на той же странице? - PullRequest
0 голосов
/ 28 июня 2018

Я тестировал несколько вещей с помощью iText7, и у меня есть сценарий, в котором мне нужно поместить абзац DocumentRenderer вверху, а затем запустить ColumnDocumentRender с двумя столбцами прямо под ним на той же странице. Проблема, с которой я сталкиваюсь, заключается в том, что когда я меняю содержимое на той же странице, оно перекрывает содержимое из DocumentRenderer с содержимым из ColumnDocumentRenderer. Я полагаю, что это потому, что один рендер не знает о другом рендере, и его содержимое начинается сверху страницы Я следовал этому уроку , но он показывает только, как добавить контент на следующую страницу. Это говорит

мы должны проинструктировать iText не сбрасывать содержимое на OutputStream

Но кто-нибудь может показать мне, как именно мы можем этого достичь?

public void createPdf(String dest) throws IOException {
    PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
    Document document = new Document(pdf);
    Paragraph p = new Paragraph()
        .add("Be prepared to read a story about a London lawyer "
        + "named Gabriel John Utterson who investigates strange "
        + "occurrences between his old friend, Dr. Henry Jekyll, "
        + "and the evil Edward Hyde.");
    document.add(p);
    document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
    ... // Define column areas
    document.setRenderer(new ColumnDocumentRenderer(document, columns));
    document.add(new AreaBreak(AreaBreakType.LAST_PAGE));   
    ... // Add novel in two columns
    document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
    document.setRenderer(new DocumentRenderer(document)); 
    document.add(new AreaBreak(AreaBreakType.LAST_PAGE));
    p = new Paragraph()
        .add("This was the story about the London lawyer "
        + "named Gabriel John Utterson who investigates strange "
        + "occurrences between his old friend, Dr. Henry Jekyll, "
        + "and the evil Edward Hyde. THE END!");
    document.add(p);
    document.close();
}

Мне нужно что-то вроде этого:

Колонки iText7

Каждый раз, когда вы создаете новый DocumentRenderer, iText начинает возвращаться к верхняя часть документа - это: с первой страницы. Это позволяет вам использовать разные средства визуализации на одном документе рядом друг с другом на та же страница. Если это необходимо, мы должны проинструктировать iText не сбросить содержимое в OutputStream; иначе у нас не будет доступа на предыдущие страницы. В этом случае нам не нужно ничего менять на предыдущие страницы. Мы просто хотим переключиться на другого рендера на следующем стр. Введение разрыва страницы на последнюю страницу позволит избежать новый контент заменяет старый.

1 Ответ

0 голосов
/ 28 июня 2018

Я взял этот код: C02E08_JekyllHydeV4

И я обновил его в соответствии с тем, что у вас есть в вашем вопросе:

//Initialize PDF document
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
// Initialize document
Document document = new Document(pdf);
Paragraph p = new Paragraph()
    .add("Be prepared to read a story about a London lawyer "
       + "named Gabriel John Utterson who investigates strange "
       + "occurrences between his old friend, Dr. Henry Jekyll, "
       + "and the evil Edward Hyde.");
document.add(p);
document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));

//Set column parameters
...
//Define column areas
...
document.setRenderer(new ColumnDocumentRenderer(document, columns)); 
document.add(new AreaBreak(AreaBreakType.LAST_PAGE));   
// Add the full Jekyl and Hyde text
document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
document.setRenderer(new DocumentRenderer(document)); 
document.add(new AreaBreak(AreaBreakType.LAST_PAGE));
p = new Paragraph()
    .add("This was the story about the London lawyer "
       + "named Gabriel John Utterson who investigates strange "
       + "occurrences between his old friend, Dr. Henry Jekyll, "
       + "and the evil Edward Hyde. THE END!");
document.add(p);
//Close document
document.close();

Результат выглядит так:

enter image description here

enter image description here

enter image description here

Я думаю, это поведение, которое вы ищете. Если это не так, пожалуйста, объясните, что идет не так.

UPDATE:

После прояснения вопроса становится ясно, что приведенный выше ответ не решает проблему. Это решение актуальной проблемы:

Нам нужно создать пользовательский ParagraphRenderer, чтобы определить Y-позицию: Класс MyParagraphRenderer расширяет ParagraphRenderer {

    float y;

    public MyParagraphRenderer(Paragraph modelElement) {
        super(modelElement);
    }

    @Override
    public void drawBorder(DrawContext drawContext) {
        super.drawBorder(drawContext);
        y = getOccupiedAreaBBox().getBottom();
    }

    public float getY() {
        return y;
    }

}

Когда мы добавляем первый абзац, нам нужно использовать этот пользовательский ParagraphRenderer:

Paragraph p = new Paragraph()
        .add("Be prepared to read a story about a London lawyer "
        + "named Gabriel John Utterson who investigates strange "
        + "occurrences between his old friend, Dr. Henry Jekyll, "
        + "and the evil Edward Hyde.");
MyParagraphRenderer renderer = new MyParagraphRenderer(p);
p.setNextRenderer(renderer);
document.add(p);

Теперь мы можем получить нужную нам позицию Y следующим образом: renderer.getY(); мы используем эту позицию Y, чтобы определить первый набор столбцов:

float offSet = 36;
float gutter = 23;
float columnWidth = (PageSize.A4.getWidth() - offSet * 2) / 2 - gutter;
float columnHeight1 = renderer.getY() - offSet * 2;
Rectangle[] columns1 = {
    new Rectangle(offSet, offSet, columnWidth, columnHeight1),
    new Rectangle(offSet + columnWidth + gutter, offSet, columnWidth, columnHeight1)};

Мы могли бы использовать этот набор столбцов для создания ColumnDocumentRenderer, но если для визуализации всего содержимого требуется более одной страницы, то смещение столбцов на второй странице будет неправильным, поэтому мы также создаем custom ColumnDocumentRenderer:

class MyColumnDocumentRenderer extends ColumnDocumentRenderer {

    Rectangle[] columns2;

    public MyColumnDocumentRenderer(Document document, Rectangle[] columns1, Rectangle[] columns2) {
        super(document, columns1);
        this.columns2 = columns2;
    }

    @Override
    protected PageSize addNewPage(PageSize customPageSize) {
        PageSize size = super.addNewPage(customPageSize);
        columns = columns2;
        return size;
    }
}

Этот ColumnDocumentRenderer принимает два набора столбцов, один набор будет использоваться на первой странице, второй набор будет использоваться на всех последующих страницах. Вот как мы определяем и применяем пользовательский ColumnDocumentRenderer:

float columnHeight2 = PageSize.A4.getHeight() - offSet * 2;
Rectangle[] columns2 = {
    new Rectangle(offSet, offSet, columnWidth, columnHeight2),
    new Rectangle(offSet + columnWidth + gutter, offSet, columnWidth, columnHeight2)};
document.setRenderer(new MyColumnDocumentRenderer(document, columns1, columns2));  

Теперь результат выглядит так:

enter image description here

В зависимости от требуемого расстояния между первым абзацем шириной страницы и последующим содержимым в столбцах, вы можете настроить значение renderer.getY() - offSet * 2.

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