Ändern der XPS-Seite zu Ereignissen | Java
Den ereignisbasierten Ansatz in der Programmierung verstehen
Der ereignisbasierte Ansatz in der Programmierung ist ein Paradigma, das sich auf Ereignisse und deren Handhabung konzentriert. In diesem Modell wird der Programmablauf durch Ereignisse bestimmt, zu denen Benutzeraktionen (z. B. Mausklicks oder Tastendrücke), vom System generierte Benachrichtigungen oder Nachrichten von anderen Anwendungen gehören können. Nachfolgend sind einige Schlüsselaspekte des ereignisbasierten Ansatzes aufgeführt:
Ereignisse: Ereignisse kennzeichnen wichtige Ereignisse innerhalb eines Programms. Diese können Benutzerinteraktionen, Datenänderungen oder Nachrichten von verschiedenen Komponenten eines Systems umfassen. Beispielsweise kann ein Klick auf eine Schaltfläche oder das Laden einer Datei Ereignisse auslösen.
Ereignis-Listener: Um Ereignisse zu verarbeiten, verwenden Programmierer Ereignis-Listener (oder Handler). Hierbei handelt es sich um Funktionen oder Methoden, die beim Eintreten eines bestimmten Ereignisses ausgeführt werden sollen. Beispielsweise kann ein Ereignis-Listener so konfiguriert werden, dass er eine Funktion ausführt, wenn ein Benutzer auf eine Schaltfläche klickt.
Asynchrone Ausführung: Das ereignisbasierte Modell erleichtert typischerweise die asynchrone Programmierung und ermöglicht es Programmen, ihre Reaktionsfähigkeit aufrechtzuerhalten, während sie auf Ereignisse warten. Beispielsweise kann eine Webanwendung weiterhin funktionieren, während sie auf Daten von einem Server wartet.
Entkopplung: Der ereignisbasierte Ansatz fördert die Entkopplung zwischen verschiedenen Komponenten eines Programms. Diese Komponenten können über Ereignisse interagieren, ohne dass Kenntnisse über die Implementierungsdetails der anderen Komponenten erforderlich sind, was zu einem modulareren und wartbareren Code führt.
Häufige Anwendungsfälle: Ereignisgesteuerte Programmierung wird häufig in grafischen Benutzeroberflächen (GUIs), Webanwendungen und Systemen eingesetzt, die Echtzeitinteraktionen erfordern. Frameworks und Bibliotheken wie Node.js, React und viele andere nutzen ereignisgesteuerte Muster.
Zustandsverwaltung: In einem ereignisgesteuerten System ist eine effektive Zustandsverwaltung unerlässlich, da die Anwendung je nach Benutzerinteraktionen oder Ereignissen in verschiedenen Zuständen vorhanden sein kann. In der Regel werden geeignete Zustandsverwaltungsstrategien implementiert, um sicherzustellen, dass die Anwendung wie vorgesehen funktioniert.
Insgesamt ist der ereignisbasierte Ansatz eine effektive Methode zur Verwaltung von Interaktionen und Arbeitsabläufen innerhalb eines Programms und eignet sich daher besonders für Anwendungen, die Reaktionsfähigkeit und Benutzerinteraktionen erfordern.
Die XPS-Dokumentkonvertierung und -Ereignisse
Wenn Sie eine bestimmte Seite eines XPS-Dokuments mithilfe der Aspose.Page-API ändern müssen, wählen Sie normalerweise das aktive Dokument aus (wenn die XPS-Datei mehrere Dokumente enthält), wählen Sie die aktive Seite aus und übernehmen Sie dann die Änderungen.
Nehmen wir nun an, Sie müssen wiederholende Änderungen auf allen Seiten einer XPS-Datei implementieren und das Ergebnis anschließend entweder in PDF oder ein Bildformat konvertieren. Beispiele für solche Änderungen könnten das Hinzufügen eines Wasserzeichens zu den Seiten oder das Einfügen von Navigations-Hyperlinks sein. Die unkomplizierte Methode zum Vornehmen solcher Änderungen besteht darin, die Dokumente im XPS-Paket zu durchsuchen, die Seiten im aktuell aktiven Dokument zu durchsuchen und schließlich Ihre Änderungen anzuwenden. Der Code zur Lösung dieser Aufgabe würde also wie folgt aussehen:
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);
Wenn Sie außerdem einige unregelmäßige Änderungen vornehmen müssen, bevor Sie die sich wiederholenden Änderungen anwenden, kann dieser Ansatz zu Verwirrung oder übermäßigem Durchlaufen von Dokumenten und Seiten führen. Außerdem können diese Schleifen etwas umständlich erscheinen. Wenn Sie ein XPS-Dokument in ein PDF oder ein Bild konvertieren, erfolgt der Vorgang Seite für Seite. Während sich der Konvertierungsauftrag auf die Verarbeitung der nächsten Seite vorbereitet, löst er ein „Before-Page“-Ereignis aus. Der Benutzer kann das Verhalten (Ereignisbehandlung) bei solchen Ereignissen definieren, indem er die Klasse BeforePageSavingEventHandler erweitert und so einige der im Einführungsabschnitt dieses Artikels erläuterten Vorteile nutzt.
Beispiel für das Hinzufügen von Navigations-Hyperlinks
In diesem Abschnitt stellen wir ein Beispiel mit Navigations-Hyperlinks vor. Und um die Aufgabe etwas komplizierter zu machen, konvertieren wir nur eine Teilmenge aller Seiten in PDF, wie durch die Methode „PdfSaveOptions.setPageNumbers()“ definiert.
Die Event-Handler-Klasse
Unten ist die Erweiterung der Klasse „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}
Die Handler-Klasse muss die Seiten kennen, die wir als PDF speichern möchten, um die richtigen Hyperlink-Ziele festzulegen. Folglich sollte der Konstruktor die Array-Eigenschaft „getPageNumbers()“ der Optionen als Argument verwenden. Wenn das Array von Seitenzahlen bereitgestellt wird, erstellen wir eine sortierte Sammlung davon und schließen gleichzeitig Duplikate aus. Darüber hinaus benötigt die Klasse ein „XpsFont“-Objekt, das die Schriftartdaten für den Hyperlinktext enthält.
In der überschriebenen Methode „handle()“ geschieht alles. Das Argument der Methode ist ein Objekt, das die Änderungs-API für die aktuelle Seite, die Dokumentnummer innerhalb des XPS-Pakets, die absolute Seitenzahl über alle Dokumente hinweg, die relative Seitenzahl innerhalb des aktuellen Dokuments (die gleich ist) enthält vorherige Nummer, wenn das Paket nur ein Dokument enthält) und die Ausgabeseitennummer (die der absoluten Seitenzahl entspricht, wenn wir das gesamte Paket konvertieren).
Die Logik der folgenden zwei „Wenn“-Blöcke ist recht einfach. Es analysiert das Ereignisargument „getOutputPageNumber()“, um gegebenenfalls einige der Links wegzulassen: Die Links [First]
und [Prev]
werden nicht zur ersten Seite hinzugefügt, während die Links „[Next]“ und „ [Letzte]
-Links werden nicht auf der letzten Seite angezeigt. Die Logik ist außerdem darauf ausgelegt, beide Szenarien zu berücksichtigen, unabhängig davon, ob Seitenzahlen angegeben sind oder nicht.
Nach den „if“-Blöcken gibt es Code, der in der unteren rechten Ecke der Seite eine Seitenzahl hinzufügt.
Die letzte Zeile fügt den Gliederungseintrag der Seite hinzu. Dies ist das Element, das im Navigationsbereich eines PDF-Viewers angezeigt wird (sofern unterstützt).
Code zur Konvertierung
Da nun der Event-Handler „before-page“ definiert ist, können wir den Code für die Dokumentkonvertierung schreiben:
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}
Wir öffnen eine XPS-Datei und erstellen dann ein Stream-Objekt mit der Schriftartdatendatei. Als nächstes instanziieren wir die Klasse „PdfSaveOptions“ und geben die Seitenzahlen an, die wir konvertieren müssen. Die folgende Zeile „verbindet“ den „before-page“-Ereignishandler über die Sammlung „getBeforePageSavingEventHandlers()“ mit dem Konvertierungsauftrag.
Jetzt müssen Sie nur noch die Konvertierung in PDF mit der Methode „saveAsPdf()“ des Dokuments durchführen.
Abschluss
In diesem Artikel haben wir die grundlegenden Aspekte des ereignisbasierten Ansatzes in der Programmierung behandelt, die direkte Methode zum Ändern von Seiten eines XPS-Dokuments untersucht und eine fortgeschrittenere Technik zum Vornehmen wiederholender Änderungen an allen Ausgabeseiten während des Konvertierungsprozesses untersucht Am Beispiel des Einfügens von Navigations-Hyperlinks.
Die vollständigen Beispiele finden Sie in unserem Beispielprojekt.