itext
ページイベント(iText 5)対イベントハンドラおよびレンダラ(iText 7)
サーチ…
備考
iText 5では、ページイベントの概念を導入し、開発者がドキュメントを開いたとき、新しいページを開いたとき、ページが終了したとき、ドキュメントが閉じられたときに特定の動作を追加できるようにしました。
ドキュメントでは、 onStartPage()
メソッドにコンテンツを追加することは禁止されていたことを明確にしました。コンテンツはonEndPage()
メソッドでのみ追加できます。また、ページイベントメソッドに渡されたDocument
オブジェクトが読み取り専用の目的でのみ渡されたことを明確にしました。 onEndPage()
メソッドでもdocument.add()
を使用することは禁じられていました。
残念なことに、多くの開発者はドキュメントを完全に無視し、次のような問題を引き起こしました。
- "OnEndPage"イベントハンドラの "'System.StackOverflowException"
- スタックオーバーフローの例外を取得するPDFを生成する例外
- PdfPageEventHelperでiTextSharp行区切り文字が消えます。
- iTextSharpエラードキュメントにはページを開く前にありません
- ...
私は、何人かの開発者がこれらの質問の重複を投稿したので、何度も奮闘したことを覚えていません。人々はしばしば彼らがなぜ厳しい答えを得るのだろうかと疑問を呈しますが、彼らの側からの努力が最小限であれば、自分自身を含めて誰もが多くの時間を節約できたことに気付きません。これらの質問はすべて「あなたが知っているマニュアルを読む」と答えることができました。
もう一つの選択肢はiTextの完全な見直しであり、こういった問題を避けることができました。
iTextが有機的に成長したため、ページイベントクラスは、ページイベントと無関係な機能を拡張しました。これには一般的なチャンク機能が含まれており、段落の開始と終了などが登録されていました。
私たちがiText 7で修正したもの:
私たちはページイベント機能を削除しました。
ページに関するすべてのイベントに対して、 IEventHandler
インターフェイスを実装し、 addEventHandler
を使用してこのハンドラをPdfDocumentEvent
としてPdfDocumentEvent
にPdfDocument
ます。この例では、 END_PAGE
イベントを使用していますが、 START_PAGE
イベントを使用することもできます。あなたが最初か最後にコンテンツを追加するかどうかはそれ以上重要ではありません。これについての詳細は、「 イベントの処理 」を参照してください。 iText 7:Building Blocksチュートリアルの第7章であるビューア設定とライターのプロパティを設定します 。
ビルディングブロックをより階層的にするという意味でビルディングブロックを改良しました( 開始する前に iText 7:Building Blocksチュートリアルの紹介であるクラスとインターフェイスの概要を参照)。また、各ビルディングブロックに1組のレンダラークラスを導入し、レンダリング時にビルディングブロックが異なる動作を示すように、開発者がこれらのレンダラーを調整できるようにしました。たとえば、 iText 7:Building BlocksチュートリアルのChapter 7であるAbstractElementオブジェクトの追加(パート1)のレンダラーの例を参照してください。
これらの変更により、PDFやiTextについて多くのことを知らない(やりたい)開発者のための機能が簡素化されると同時に、iTextコードを深く掘り下げて開発者を作成することを恐れることのない開発者にも豊富な柔軟性を提供しますPDFは彼らが望むのとまったく同じです。
もっと知りたい? 無料の電子ブックを手に入れよう!
Text2PdfPageEvents.java(iText 5)
次のテキストファイルがあるとします。jekyll_hyde.txt
どうすればこのようなPDFに変換できますか?
タイトルに追加される青色の境界線、および各ページの下部にあるページ番号に注意してください。 iText 5では、これらの要素はページイベントを使用して追加されます:
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();
}
}
コードを再利用して、テキストファイルをText2Pdf.java(iText 5)の例のPDFに変換し、ページイベントを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();
}
Text2PdfPageEvents1.java(iText 7)
次のテキストファイルがあるとします。jekyll_hyde.txt
どうすればこのようなPDFに変換できますか?
各ページの下部にページ番号を記入してください。これらは、 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);
}
}
Text2Pdf.java(iText 7)の例は、2つのマイナーな変更だけで再利用できます。
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();
}
ページが終了するたびにFooter
クラスのhandleEvent()
メソッドをトリガーするイベントハンドラを追加します。また、タイトルに使用されるParagraph
オブジェクトの枠線を定義します。
出典: developers.itextpdf.comおよびiText 7:Building Blocksチュートリアル
Text2PdfPageEvents2.java
次のテキストファイルがあるとします。jekyll_hyde.txt
どうすればこのようなPDFに変換できますか?
これは前の記事と非常によく似ていますが、タイトルの境界線は丸みを帯びています。これを実現するカスタムParagraphRenderer
を作成し、そのレンダラーを使用するTitleParagraph
オブジェクトを作成しました。
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();
}
};
}
}
テキストをPDFに変換するためのコードはとても簡単です。タイトルのフォントを太字にする必要がなくなり、境界を定義する必要がなくなりました。
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();
}
出典: developers.itextpdf.comおよびiText 7:Building Blocksチュートリアル