Szukaj…


Uwagi

W iText 5 wprowadziliśmy koncepcję zdarzeń na stronie, aby umożliwić programistom dodanie określonych zachowań podczas otwierania dokumentu, otwierania nowej strony, kończenia strony i zamykania dokumentu.

W dokumentacji wyraźnie stwierdziliśmy, że zabronione jest dodawanie treści w onStartPage() ; zawartość można dodać tylko w onEndPage() . Wyjaśniliśmy również bardzo wyraźnie, że obiekt Document przekazany do metod zdarzeń strony został przekazany wyłącznie do odczytu . Zabronione było używanie document.add() nawet w onEndPage() .

Niestety wielu programistów całkowicie ignoruje dokumentację, co doprowadziło do problemów takich jak:

Nie pamiętam, ile razy byłem wzburzony, ponieważ inny programista opublikował duplikat tych pytań. Ludzie często zastanawiają się, dlaczego otrzymują trudną odpowiedź, ale nie zdają sobie sprawy, że minimum wysiłku z ich strony zaoszczędziłoby wszystkim, w tym sobie, mnóstwo czasu. Na wszystkie te pytania można było odpowiedzieć, mówiąc „Przeczytaj (wiesz, który) podręcznik”.

Inną opcją był całkowity przegląd iText, aby uniknąć tego rodzaju problemów.

Ze względu na organiczny rozwój iText klasa zdarzeń stron została również rozszerzona o funkcjonalność niezwiązaną ze zdarzeniami strony. Zawierał ogólną funkcjonalność fragmentu , rejestrował początek i koniec akapitów i tak dalej.

Co naprawiliśmy w iText 7:

Usunęliśmy funkcję zdarzenia strony.

W przypadku wszystkich zdarzeń dotyczących stron wdrażamy teraz interfejs IEventHandler i używamy addEventHandler aby dodać ten PdfDocumentEvent obsługi jako PdfDocumentEvent do PdfDocument . W tym przykładzie używamy zdarzenia END_PAGE , ale moglibyśmy również użyć zdarzenia START_PAGE . Nie ma już znaczenia, czy dodasz treść na początku, czy na końcu. Więcej informacji na ten temat można znaleźć w części Obsługa wydarzeń; ustawianie preferencji przeglądarki i właściwości programu piszącego, który znajduje się w rozdziale 7 samouczka iText 7: Building Blocks .

Ulepszyliśmy bloki konstrukcyjne w tym sensie, że uczyniliśmy je bardziej hierarchicznymi (zobacz Zanim zaczniemy: Przegląd klas i interfejsów, który jest wprowadzeniem do samouczka iText 7: Bloki konstrukcyjne ). Wprowadziliśmy również zestaw klas Renderer, po jednej dla każdego bloku konstrukcyjnego, i pozwalamy programistom dostosować te renderery, aby podczas renderowania blok konstrukcyjny wykazywał inne zachowanie. Zobacz na przykład przykład mechanizmu renderującego w części Dodawanie obiektów AbstractElement (część 1), który jest rozdziałem 7 w samouczku iText 7: Building Blocks .

Zmiany te upraszczają funkcjonalność dla programistów, którzy nie chcą (dużo) wiedzą o plikach PDF i iText, a jednocześnie oferują dużą elastyczność dla programistów, którzy nie boją się zagłębić się w kod iText, aby utworzyć PDF dokładnie tak, jak tego chcą.

Chcieć wiedzieć więcej? Zdobądź bezpłatny ebook!

Text2PdfPageEvents.java (iText 5)

Załóżmy, że mamy następujący plik tekstowy: jekyll_hyde.txt

Jak przekonwertować go na plik PDF, który wygląda następująco:

wprowadź opis zdjęcia tutaj

Zwróć uwagę na niebieską ramkę dodaną do tytułów i numer strony na dole każdej strony. W iText 5 elementy te są dodawane przy użyciu zdarzeń strony:

class MyPageEvents extends PdfPageEventHelper {

    protected float startpos = -1;
    protected boolean title = true;

    public void setTitle(boolean title) {
        this.title = title;
    }

    @Override
    public void onEndPage(PdfWriter writer, Document document) {
        Rectangle pagesize = document.getPageSize();
        ColumnText.showTextAligned(
            writer.getDirectContent(),
            Element.ALIGN_CENTER,
            new Phrase(String.valueOf(writer.getPageNumber())),
            (pagesize.getLeft() + pagesize.getRight()) / 2,
            pagesize.getBottom() + 15,
            0);
        if (startpos != -1)
            onParagraphEnd(writer, document,
                pagesize.getBottom(document.bottomMargin()));
        startpos = pagesize.getTop(document.topMargin());
    }

    @Override
    public void onParagraph(PdfWriter writer, Document document,
        float paragraphPosition) {
        startpos = paragraphPosition;
    }

    @Override
    public void onParagraphEnd(PdfWriter writer, Document document,
        float paragraphPosition) {
        if (!title) return;
        PdfContentByte canvas = writer.getDirectContentUnder();
        Rectangle pagesize = document.getPageSize();
        canvas.saveState();
        canvas.setColorStroke(BaseColor.BLUE);
        canvas.rectangle(
            pagesize.getLeft(document.leftMargin()),
            paragraphPosition - 3,
            pagesize.getWidth() - document.leftMargin() - document.rightMargin(),
            startpos - paragraphPosition);
        canvas.stroke();
        canvas.restoreState();
    }
}

Możemy ponownie użyć kodu do konwersji pliku tekstowego na plik PDF z przykładu Text2Pdf.java (iText 5) i wprowadzić zdarzenie strony do PdfWriter :

public void createPdf(String dest)
throws DocumentException, IOException {
    Document document = new Document();
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
    MyPageEvents events = new MyPageEvents();
    writer.setPageEvent(events);
    document.open();
    BufferedReader br = new BufferedReader(new FileReader(TEXT));
    String line;
    Paragraph p;
    Font normal = new Font(FontFamily.TIMES_ROMAN, 12);
    Font bold = new Font(FontFamily.TIMES_ROMAN, 12, Font.BOLD);
    boolean title = true;
    while ((line = br.readLine()) != null) {
        p = new Paragraph(line, title ? bold : normal);
        p.setAlignment(Element.ALIGN_JUSTIFIED);
        events.setTitle(title);
        document.add(p);
        title = line.isEmpty();
    }
    document.close();
}

Źródło: developers.itextpdf.com

Text2PdfPageEvents1.java (iText 7)

Załóżmy, że masz następujący plik tekstowy: jekyll_hyde.txt

Jak przekonwertować go na plik PDF, który wygląda następująco:

wprowadź opis zdjęcia tutaj

Zanotuj numery stron u dołu każdej strony. Są one dodawane przy użyciu implementacji IEventHandler :

protected class Footer implements IEventHandler {

    @Override
    public void handleEvent(Event event) {
        PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
        PdfDocument pdf = docEvent.getDocument();
        PdfPage page = docEvent.getPage();
        Rectangle pageSize = page.getPageSize();
        PdfCanvas pdfCanvas = new PdfCanvas(
            page.getLastContentStream(), page.getResources(), pdf);
        Canvas canvas = new Canvas(pdfCanvas, pdf, pageSize);
        float x = (pageSize.getLeft() + pageSize.getRight()) / 2;
        float y = pageSize.getBottom() + 15;
        canvas.showTextAligned(
            String.valueOf(pdf.getPageNumber(page)),
            x, y, TextAlignment.CENTER);
    }
}

Możemy ponownie użyć przykładu Text2Pdf.java (iText 7) z tylko dwiema drobnymi zmianami:

public void createPdf(String dest) throws IOException {
    PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
    pdf.addEventHandler(PdfDocumentEvent.END_PAGE, new Footer());
    Document document = new Document(pdf)
        .setTextAlignment(TextAlignment.JUSTIFIED);
    BufferedReader br = new BufferedReader(new FileReader(TEXT));
    String line;
    PdfFont normal = PdfFontFactory.createFont(FontConstants.TIMES_ROMAN);
    PdfFont bold = PdfFontFactory.createFont(FontConstants.TIMES_BOLD);
    boolean title = true;
    Border border = new SolidBorder(Color.BLUE, 1);
    while ((line = br.readLine()) != null) {
        document.add(new Paragraph(line)
            .setFont(title ? bold : normal)
            .setBorder(title ? border : Border.NO_BORDER));
        title = line.isEmpty();
    }
    document.close();
}

Dodajemy handleEvent() obsługi zdarzeń, który będzie uruchamiał handleEvent() klasy Footer każdym razem, gdy strona się kończy. Definiujemy również granicę dla obiektów Paragraph które są używane dla tytułu.

Źródło: developers.itextpdf.com i samouczek iText 7: Building Blocks .

Text2PdfPageEvents2.java

Załóżmy, że masz następujący plik tekstowy: jekyll_hyde.txt

Jak przekonwertować go na plik PDF, który wygląda następująco:

wprowadź opis zdjęcia tutaj

Zauważ, że jest to bardzo podobne do tego, co mieliśmy wcześniej, ale granica tytułów ma teraz zaokrąglone rogi. Stworzyliśmy zwyczaj ParagraphRenderer aby to osiągnąć, a my stworzyliśmy TitleParagraph obiekt, który wykorzystuje mechanizm renderujący, że:

public class TitleParagraph extends Paragraph {

    public TitleParagraph(String line) {
        super(line);
        try {
            setFont(PdfFontFactory.createFont(FontConstants.TIMES_BOLD));
        }
        catch (IOException ioe) {
        }
    }

    @Override
    protected IRenderer makeNewRenderer() {
        return new ParagraphRenderer(this) {
            @Override
            public void drawBorder(DrawContext drawContext) {
                Rectangle occupiedAreaBBox = getOccupiedAreaBBox();
                float[] margins = getMargins();
                Rectangle rectangle = applyMargins(occupiedAreaBBox, margins, false);
                PdfCanvas canvas = drawContext.getCanvas();
                canvas.roundRectangle(rectangle.getX() - 1, rectangle.getY() - 1,
                rectangle.getWidth() + 2, rectangle.getHeight() + 2, 5).stroke();
            }
        };
    } 
}

Nasz kod do konwersji tekstu na PDF jest teraz bardzo prosty. Nie musimy już ustawiać pogrubionej czcionki dla tytułów i nie musimy już definiować ramki:

public void createPdf(String dest) throws IOException {
    PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
    pdf.addEventHandler(PdfDocumentEvent.END_PAGE, new Footer());
    Document document = new Document(pdf)
        .setTextAlignment(TextAlignment.JUSTIFIED);
    BufferedReader br = new BufferedReader(new FileReader(TEXT));
    String line;
    PdfFont normal = PdfFontFactory.createFont(FontConstants.TIMES_ROMAN);
    boolean title = true;
    Border border = new SolidBorder(Color.BLUE, 1);
    while ((line = br.readLine()) != null) {
        if (title)
            document.add(new TitleParagraph(line));
        else
            document.add(new Paragraph(line).setFont(normal));
        title = line.isEmpty();
    }
    document.close();
}

Źródło: developers.itextpdf.com i samouczek iText 7: Building Blocks .



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow