イベント発生時のXPSページの変更 | Java

プログラミングにおけるイベントベースアプローチの理解

プログラミングにおけるイベントベースアプローチは、イベントとその処理に重点を置いたパラダイムです。このモデルでは、プログラムの流れはイベントによって決定されます。イベントには、ユーザーアクション(マウスのクリックやキーの押下など)、システムによって生成される通知、他のアプリケーションからのメッセージなどが含まれます。以下は、イベントベースアプローチの主要な側面です。

全体として、イベントベースのアプローチは、プログラム内のインタラクションとワークフローを管理する効果的な方法であり、応答性とユーザーインタラクションが求められるアプリケーションに特に適しています。

XPS ドキュメントの変換とイベント

Aspose.Page API を使用して XPS ドキュメントの特定のページを変更する必要がある場合、通常はアクティブなドキュメント(XPS ファイル内に複数のドキュメントがある場合)を選択し、アクティブなページを選択して変更を適用します。

さて、XPSファイルの全ページにわたって繰り返し変更を実装し、その結果をPDFまたは画像形式に変換する必要があるとします。このような変更の例としては、ページへの透かしの追加やナビゲーションハイパーリンクの挿入などが挙げられます。このような変更を行う最も簡単な方法は、XPSパッケージ内のドキュメントを走査し、現在アクティブなドキュメントのページを走査し、最後に変更を適用するというものです。したがって、このタスクを実現するコードは次のようになります。

 1for (int i = 1; i <= document.getDocumentCount(); i++)
 2{
 3    document.selectActiveDocument(i);
 4    for (j = 1; j <= document.getPageCount(); j++)
 5    {
 6        document.selectActivePage(j);
 7        // Your changes ...
 8    }
 9}
10document.saveAsPdf("file-name.pdf", saveOptions);

繰り返し変更を適用する前に、不規則な変更も加える必要がある場合、このアプローチは混乱を招き、ドキュメントやページ間のトラバーサルが過剰になる可能性があります。また、これらのループはやや煩雑に見えるかもしれません。

XPSドキュメントをPDFまたは画像に変換する場合、処理は1ページずつ実行されます。変換ジョブが次のページの処理を準備すると、「before-page」イベントがトリガーされます。ユーザーは、 BeforePageSavingEventHandlerクラスを拡張することで、このようなイベント時の動作(イベント処理)を定義できます。これにより、この記事の導入セクションで説明した利点の一部を活用できます。

ナビゲーションハイパーリンクの追加例

このセクションでは、ナビゲーションハイパーリンクを使用する例を示します。さらに、タスクを少し複雑にするために、PdfSaveOptions.setPageNumbers() メソッドで定義されているように、全ページのサブセットのみを PDF に変換します。

イベントハンドラークラス

以下は、BeforePageSavingEventHandler クラスの拡張です。

 1/**
 2 * The class to handle the before-page event while converting an XPS document.
 3 */
 4public static class NavigationInjector extends BeforePageSavingEventHandler
 5{
 6    private final XpsFont _font;
 7    private List<Integer> _pageNumbers;
 8
 9    public NavigationInjector(XpsFont font, int[] pageNumbers)
10    {
11        _font = font;
12        if (pageNumbers == null || pageNumbers.length == 0)
13            return;
14
15        // Turn the page number array into a sorted collection of unique values.
16        SortedMap<Integer, Integer> map = new TreeMap<Integer, Integer>();
17        for (int pn : pageNumbers)
18            map.put(pn, 0);
19        _pageNumbers = new ArrayList<Integer>(map.keySet());
20    }
21
22    /**
23     * The action itself to be triggered on a before-page event.
24     * @param args The even arguments.
25     */
26    @Override
27    public void handle(BeforeSavingEventArgs<PageAPI> args)
28    {
29        PageAPI api = args.getElementAPI();
30
31        XpsGlyphs glyphs;
32        // For all pages in the output PDF except the first one...
33        if (args.getOutputPageNumber() > 1)
34        {
35          // ...insert a hyperlink to the first page...
36            glyphs = api.createGlyphs(_font, 15f, 5f, api.getHeight() - 10f, "[First]");
37            glyphs.setFill(api.createSolidColorBrush(Color.BLUE));
38            glyphs.setHyperlinkTarget(new XpsPageLinkTarget(_pageNumbers == null ? 1 : _pageNumbers.get(0)));
39            api.add(glyphs);
40
41            // ...and to the previous page.
42            glyphs = api.createGlyphs(_font, 15f, 60f, api.getHeight() - 10f, "[Prev]");
43            glyphs.setFill(api.createSolidColorBrush(Color.BLUE));
44            glyphs.setHyperlinkTarget(new XpsPageLinkTarget(
45                _pageNumbers == null ? args.getAbsolutePageNumber() - 1 : _pageNumbers.get(args.getOutputPageNumber() - 2)));
46            api.add(glyphs);
47        }
48
49        // For all pages in the output PDF except the last one...
50        if ((_pageNumbers != null && args.getOutputPageNumber() < _pageNumbers.size()) ||
51            (_pageNumbers == null && args.getOutputPageNumber() < api.getTotalPageCount()))
52        {
53          // ...insert a hyperlink to the next page...
54            glyphs = api.createGlyphs(_font, 15f, 110f, api.getHeight() - 10f, "[Next]");
55            glyphs.setFill(api.createSolidColorBrush(Color.BLUE));
56            glyphs.setHyperlinkTarget(new XpsPageLinkTarget(
57                _pageNumbers == null ? args.getAbsolutePageNumber() + 1 : _pageNumbers.get(args.getOutputPageNumber())));
58            api.add(glyphs);
59
60            // ...and to the last page.
61            glyphs = api.createGlyphs(_font, 15f, 160f, api.getHeight() - 10f, "[Last]");
62            glyphs.setFill(api.createSolidColorBrush(Color.BLUE));
63            glyphs.setHyperlinkTarget(new XpsPageLinkTarget(
64                _pageNumbers == null ? api.getTotalPageCount() : _pageNumbers.get(_pageNumbers.size() - 1)));
65            api.add(glyphs);
66        }
67
68        // Insert a page number in the bottom-right corner.
69        glyphs = api.createGlyphs(_font, 15f, api.getWidth() - 20f, api.getHeight() - 10f, Integer.toString(args.getOutputPageNumber()));
70        glyphs.setFill(api.createSolidColorBrush(Color.BLACK));
71        api.add(glyphs);
72
73        // Add an outline entry to display the links to the converted pages in the navigation pane of a PDF viewer.
74        api.addOutlineEntry(MessageFormat.format("Page {0}", args.getOutputPageNumber()), 1, args.getAbsolutePageNumber());
75    }
76}

ハンドラークラスは、正しいハイパーリンクターゲットを確立するために、PDF として保存するページを認識する必要があります。そのため、コンストラクターはオプションの getPageNumbers() 配列プロパティを引数として受け取る必要があります。ページ番号の配列が指定された場合は、重複を除外しながらソートされたコレクションを作成します。さらに、クラスにはハイパーリンクテキストのフォントデータを含む XpsFont オブジェクトが必要です。

オーバーライドされた handle() メソッドですべてが行われます。このメソッドの引数は、現在のページの変更 API、XPS パッケージ内のドキュメント番号、すべてのドキュメントにわたる 絶対ページ番号、現在のドキュメント内の 相対ページ番号(パッケージ内にドキュメントが 1 つしかない場合は前の番号と同じ)、および 出力ページ番号(パッケージ全体を変換した場合の絶対ページ番号と同じ)を含むオブジェクトです。

次の 2 つの if ブロックのロジックは非常にシンプルです。 getOutputPageNumber() イベント引数を分析し、必要に応じて一部のリンクを省略します。[First] および [Prev] リンクは最初のページには追加されず、[Next] および [Last] リンクは最後のページには表示されません。また、ページ番号が指定されているかどうかに関係なく、両方のシナリオに対応できるようにロジックが設計されています。

if ブロックの後に、ページの右下隅にページ番号を追加するコードがあります。

最後の行では、ページのアウトラインエントリを追加します。これは、PDF ビューアー(サポートされている場合)のナビゲーションパネルに表示される項目です。

変換用のコード

「before-page」イベントハンドラが定義されたので、ドキュメント変換用のコードを記述できます。

 1// For complete examples and data files, please go to https://github.com/aspose-page/Aspose.Page-for-Java
 2// The path to the documents directory.
 3String dataDir = Utils.getDataDir();
 4String fontDir = dataDir + "necessary_fonts/";
 5// Open an XPS Document
 6final XpsDocument doc = new XpsDocument(dataDir + "Sample3.xps");
 7try {
 8  // Create a font
 9  final InputStream fontStream = new FileInputStream(fontDir + "arialbd.ttf");
10  try {
11    // Create options for conversion to PDF
12    PdfSaveOptions options = new PdfSaveOptions();
13    // Set the filter for the pages that need conversion
14    options.setPageNumbers(new int[] { 2, 6, 7, 13 });
15    // Add the event handler that will execute right before the conversion of each page
16    options.getBeforePageSavingEventHandlers().add(new NavigationInjector(doc.createFont(fontStream), options.getPageNumbers()));
17    // Save resultant XPS document
18    doc.saveAsPdf(dataDir + "ModifyPageOnConversion_out.pdf", options);
19  } finally {
20    if (fontStream != null)
21      fontStream.close();
22  }
23} finally {
24  if (doc != null)
25    doc.close();
26}

XPSファイルを開き、フォントデータファイルを含むストリームオブジェクトを作成します。次に、PdfSaveOptionsクラスをインスタンス化し、変換するページ番号を指定します。次の行は、getBeforePageSavingEventHandlers()コレクションを介して、「before-page」イベントハンドラーを変換ジョブに「接続」します。

あとは、ドキュメントのsaveAsPdf()メソッドを使用してPDFへの変換を実行するだけです。

まとめ

この記事では、プログラミングにおけるイベントベースのアプローチの基本的な側面を解説し、XPSドキュメントのページを直接変更する方法を検証しました。さらに、ナビゲーションハイパーリンクの挿入を例に、変換プロセス中にすべての出力ページに繰り返し変更を加えるためのより高度な手法についても考察しました。

完全な例については、 サンプルプロジェクトをご覧ください。

Have any questions about Aspose.Page?



Subscribe to Aspose Product Updates

Get monthly newsletters & offers directly delivered to your mailbox.