Modification de la page XPS sur les événements | Java
Comprendre l’approche événementielle en programmation
L’approche événementielle en programmation est un paradigme axé sur les événements et leur gestion. Dans ce modèle, le flux du programme est dicté par des événements, qui peuvent inclure des actions de l’utilisateur (telles que des clics de souris ou des pressions sur des touches), des notifications générées par le système ou des messages provenant d’autres applications. Vous trouverez ci-dessous quelques aspects clés de l’approche événementielle :
Événements : les événements signifient des événements importants au sein d’un programme. Ceux-ci peuvent englober les interactions des utilisateurs, les modifications de données ou les messages provenant de différents composants d’un système. Par exemple, un clic sur un bouton ou le chargement d’un fichier peut déclencher des événements.
Écouteurs d’événements : pour gérer les événements, les programmeurs emploient des écouteurs d’événements (ou gestionnaires). Il s’agit de fonctions ou de méthodes désignées pour s’exécuter lorsqu’un événement particulier se produit. Par exemple, un écouteur d’événements peut être configuré pour exécuter une fonction lorsqu’un utilisateur clique sur un bouton.
Exécution asynchrone : le modèle basé sur les événements facilite généralement la programmation asynchrone, permettant aux programmes de maintenir leur réactivité en attendant les événements. Par exemple, une application Web peut continuer à fonctionner pendant qu’elle attend les données d’un serveur.
Découplage : l’approche basée sur les événements encourage le découplage entre les différentes composantes d’un programme. Ces composants peuvent interagir via des événements sans nécessiter de connaissance des détails d’implémentation de chacun, ce qui donne lieu à un code plus modulaire et plus maintenable.
Cas d’utilisation courants : la programmation basée sur les événements est couramment utilisée dans les interfaces utilisateur graphiques (GUI), les applications Web et les systèmes qui nécessitent des interactions en temps réel. Les frameworks et bibliothèques tels que Node.js, React et bien d’autres exploitent des modèles basés sur les événements.
Gestion des états : dans un système piloté par événements, une gestion efficace des états est essentielle, car l’application peut exister dans différents états en fonction des interactions ou des événements de l’utilisateur. Des stratégies de gestion d’état appropriées sont généralement mises en œuvre pour garantir que l’application fonctionne comme prévu.
Dans l’ensemble, l’approche basée sur les événements est une méthode efficace pour gérer les interactions et les flux de travail au sein d’un programme, ce qui la rend particulièrement adaptée aux applications qui exigent de la réactivité et des interactions avec les utilisateurs.
La conversion et les événements du document XPS
Lorsque vous devez modifier une page spécifique d’un document XPS à l’aide de l’API Aspose.Page, vous sélectionnez généralement le document actif (s’il existe plusieurs documents dans le fichier XPS), sélectionnez la page active, puis appliquez les modifications.
Supposons maintenant que vous deviez implémenter des modifications répétitives sur toutes les pages d’un fichier XPS, puis convertir le résultat au format PDF ou image. Des exemples de tels changements peuvent inclure l’ajout d’un filigrane aux pages ou l’insertion d’hyperliens de navigation. La méthode simple pour effectuer de telles modifications consiste à parcourir les documents du package XPS, à parcourir les pages du document actif actuel, puis, enfin, à appliquer vos modifications. Ainsi, le code pour réaliser cette tâche ressemblerait à ceci :
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);
Si vous devez également apporter des modifications irrégulières avant d’appliquer les modifications répétitives, cette approche peut entraîner une confusion ou des parcours excessifs dans les documents et les pages. De plus, ces boucles peuvent paraître quelque peu encombrantes. Lorsque vous convertissez un document XPS en PDF ou en image, le processus se déroule page par page. Lorsque la tâche de conversion se prépare à traiter la page suivante, elle déclenche un événement « avant la page ». L’utilisateur peut définir le comportement (gestion des événements) sur de tels événements en étendant la classe BeforePageSavingEventHandler, tirant ainsi parti de certains des avantages évoqués dans la section d’introduction de cet article.
Exemple d’ajout d’hyperliens de navigation
Dans cette section, nous présenterons un exemple impliquant des hyperliens de navigation. Et pour rendre la tâche un peu plus compliquée, nous allons convertir uniquement un sous-ensemble de toutes les pages en PDF, tel que défini par la méthode PdfSaveOptions.setPageNumbers()
.
La classe du gestionnaire d’événements
Ci-dessous se trouve l’extension de la classe 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}
La classe de gestionnaire doit connaître les pages que nous avons l’intention d’enregistrer au format PDF afin d’établir les cibles de liens hypertexte correctes. Par conséquent, le constructeur doit prendre la propriété de tableau des options getPageNumbers()
comme argument. Si le tableau des numéros de page est fourni, nous créons une collection triée de ceux-ci, excluant en même temps les doublons. De plus, la classe a besoin d’un objet « XpsFont » qui contient les données de police pour le texte du lien hypertexte.
La méthode handle()
remplacée est l’endroit où tout se passe. L’argument de la méthode est un objet qui contient l’API de modification pour la page actuelle, le numéro du document dans le package XPS, le numéro de page absolu dans tous les documents, le numéro de page relatif dans le document actuel (qui est égal au numéro précédent s’il n’y a qu’un seul document dans le package), et le numéro de page de sortie (qui est égal au numéro de page absolu lorsque nous convertissons l’ensemble du package).
La logique des deux blocs « if » suivants est assez simple. Il analyse l’argument de l’événement getOutputPageNumber()
pour omettre certains liens le cas échéant : les liens [First]
et [Prev]
ne seront pas ajoutés à la première page, tandis que les [Next]
et ` Les liens [Dernier] n’apparaîtront pas sur la dernière page. La logique est également conçue pour s’adapter aux deux scénarios, que les numéros de page soient spécifiés ou non.
Après les blocs « if », il y a du code qui ajoute un numéro de page dans le coin inférieur droit de la page.
La dernière ligne ajoute l’entrée de plan de la page, qui est l’élément qui sera affiché dans le volet de navigation d’une visionneuse PDF (si pris en charge).
Code de conversion
Maintenant que le gestionnaire d’événements “page avant” est défini, nous pouvons écrire le code pour la conversion du document :
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}
Nous ouvrons un fichier XPS puis créons un objet flux avec le fichier de données de police. Ensuite, nous instancions la classe PdfSaveOptions
et spécifions les numéros de page que nous devons convertir. La ligne suivante “connecte” le gestionnaire d’événements “before-page” au travail de conversion via la collection getBeforePageSavingEventHandlers()
.
Il ne reste plus qu’à exécuter la conversion en PDF en utilisant la méthode saveAsPdf()
du document.
Conclusion
Dans cet article, nous avons couvert les aspects fondamentaux de l’approche basée sur les événements en programmation, examiné la méthode directe de modification des pages d’un document XPS et exploré une technique plus avancée pour apporter des modifications répétitives à toutes les pages de sortie pendant le processus de conversion. , en prenant comme exemple l’insertion d’hyperliens de navigation.
Pour les exemples complets, explorez notre Exemple de projet.