修改 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 或图像时,该过程一次进行一页。当转换作业准备处理下一页时,它会触发“before-page”事件。用户可以通过扩展 BeforePageSavingEventHandler 类来定义此类事件的行为(事件处理),从而利用本文简介部分讨论的一些优势。

添加导航超链接的示例

在本节中,我们将介绍一个涉及导航超链接的示例。为了使任务稍微复杂一些,我们将仅将所有页面的子集转换为 PDF,如 PdfSaveOptions.setPageNumbers() 方法所定义。

事件处理程序类

以下是 BeforePageSavingEventHandler 类的扩展:

 1// The class to handle the before-page event while converting an XPS document.
 2private static class NavigationInjector extends BeforePageSavingEventHandler {
 3    // The font in which navigation hyperlinks and page numbers will be displayed.
 4    private final XpsFont font;
 5    // The page numbers to convert.
 6    private final TreeMap<Integer, Integer> pageNumbers;
 7
 8    public NavigationInjector(XpsFont font, int[] pageNumbers) {
 9        this.font = font;
10        if (pageNumbers == null) {
11            this.pageNumbers = null;
12            return;
13        }
14
15        // Turn the page number array into a sorted collection of unique values.
16        this.pageNumbers = new TreeMap<>();
17        for (int pn : pageNumbers) {
18            this.pageNumbers.put(pn, 0);
19        }
20    }
21
22    /**
23     * The action itself to be triggered on a before-page event.
24     *
25     * @param args The event arguments.
26     */
27    @Override
28    public void handle(BeforeSavingEventArgs<PageAPI> args) {
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            // ...insert a hyperlink to the first page...
35            glyphs = api.createGlyphs(font, 15f, 5f, api.getHeight() - 10f, "[First]");
36            glyphs.setFill(api.createSolidColorBrush(Color.BLUE));
37            glyphs.setHyperlinkTarget(new XpsPageLinkTarget(pageNumbers == null ? 1 : pageNumbers.firstKey()));
38            api.add(glyphs);
39
40            // ...and to the previous page.
41            glyphs = api.createGlyphs(font, 15f, 60f, api.getHeight() - 10f, "[Prev]");
42            glyphs.setFill(api.createSolidColorBrush(Color.BLUE));
43            glyphs.setHyperlinkTarget(new XpsPageLinkTarget(
44                pageNumbers == null ? args.getAbsolutePageNumber() - 1 : 
45                pageNumbers.keySet().toArray(new Integer[0])[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            // ...insert a hyperlink to the next page...
53            glyphs = api.createGlyphs(font, 15f, 110f, api.getHeight() - 10f, "[Next]");
54            glyphs.setFill(api.createSolidColorBrush(Color.BLUE));
55            glyphs.setHyperlinkTarget(new XpsPageLinkTarget(
56                pageNumbers == null ? args.getAbsolutePageNumber() + 1 : 
57                pageNumbers.keySet().toArray(new Integer[0])[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() : 
65                pageNumbers.lastKey()));
66            api.add(glyphs);
67        }
68
69        // Insert a page number in the bottom-right corner.
70        glyphs = api.createGlyphs(font, 15f, api.getWidth() - 20f, api.getHeight() - 10f, 
71            String.valueOf(args.getOutputPageNumber()));
72        glyphs.setFill(api.createSolidColorBrush(Color.BLACK));
73        api.add(glyphs);
74
75        // Add an outline entry to display the links to the converted pages in the navigation pane of a PDF viewer.
76        api.addOutlineEntry(String.format("Page %d", args.getOutputPageNumber()), 1, args.getAbsolutePageNumber());
77    }
78}

处理程序类需要知道我们打算保存为 PDF 的页面,以便建立正确的超链接目标。因此,构造函数应该将选项的 getPageNumbers() 数组属性作为参数。如果提供了页码数组,我们将创建一个已排序的页码集合,同时排除重复项。此外,该类需要一个 XpsFont 对象,其中包含超链接文本的字体数据。

所有操作都发生在重写的 handle() 方法中。该方法的参数是一个对象,其中包含当前页面的修改 API、XPS 包中的文档编号、所有文档的 绝对页码、当前文档中的 相对页码(如果包中只有一个文档,则等于之前的页码)以及 输出页码(当我们转换整个包时,它等于绝对页码)。

以下两个 if 块的逻辑非常简单。它分析 getOutputPageNumber() 事件参数,并在适当的情况下省略一些链接:[First][Prev] 链接不会添加到第一页,而 [Next][Last] 链接不会出现在最后一页。该逻辑也设计为同时适应这两种情况,无论是否指定页码。

if 块之后,有一段代码用于在页面的右下角添加页码。

最后一行添加了页面的大纲条目,该条目将显示在 PDF 查看器(如果支持)的导航窗格中。

转换代码

现在“before-page”事件处理程序已定义,我们可以编写文档转换的代码了:

 1// Modify page on conversion event.
 2
 3// Open an XPS document
 4try (XpsDocument doc = new XpsDocument(getDataDir() + "Sample3.xps");
 5     // Create a font
 6     FileInputStream fontStream = new FileInputStream(getDataDir() + "arialbd.ttf")) {
 7        
 8    // Create options for conversion to PDF
 9    PdfSaveOptions options = new PdfSaveOptions();
10    // Set the filter for the pages that need conversion
11    options.setPageNumbers(new int[] { 2, 6, 7, 13 });
12    // Add the event handler that will execute right before the conversion of each page
13    options.getBeforePageSavingEventHandlers().add(new NavigationInjector(doc.createFont(fontStream), options.getPageNumbers()));
14    // Save resultant XPS document
15    doc.saveAsPdf(getOutputDir() + "ModifyPageOnConversion_out.pdf", options);
16}

我们打开一个 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.