Зміна сторінки XPS на події | Java
Розуміння подійного підходу в програмуванні
Подієвий підхід у програмуванні — це парадигма, зосереджена на подіях та їх обробці. У цій моделі потік програми диктується подіями, які можуть включати дії користувача (такі як клацання мишею або натискання клавіш), сповіщення, створені системою, або повідомлення від інших програм. Нижче наведено деякі ключові аспекти підходу на основі подій:
Події: події означають важливі події в програмі. Вони можуть охоплювати взаємодії користувача, зміни даних або повідомлення від різних компонентів системи. Наприклад, натискання кнопки або завантаження файлу можуть викликати події.
Прослуховувачі подій: для обробки подій програмісти використовують прослуховувачі подій (або обробники). Це функції або методи, призначені для запуску, коли відбувається певна подія. Наприклад, слухач подій може бути налаштований на виконання функції, коли користувач натискає кнопку.
Асинхронне виконання: модель на основі подій зазвичай полегшує асинхронне програмування, дозволяючи програмам підтримувати оперативність під час очікування подій. Наприклад, веб-додаток може продовжувати функціонувати, очікуючи даних із сервера.
Відокремлення: підхід, заснований на подіях, сприяє відокремленню різних компонентів програми. Ці компоненти можуть взаємодіяти через події, не вимагаючи знання деталей реалізації один одного, що призводить до більш модульного коду, який можна підтримувати.
Поширені випадки використання: програмування, кероване подіями, зазвичай використовується в графічних інтерфейсах користувача (GUI), веб-додатках і системах, які вимагають взаємодії в реальному часі. Фреймворки та бібліотеки, такі як Node.js, React та багато інших, використовують шаблони, керовані подіями.
Управління станом: у керованій подіями системі ефективне керування станом є важливим, оскільки програма може перебувати в різних станах залежно від взаємодії користувача або подій. Відповідні стратегії управління станом зазвичай реалізуються, щоб гарантувати, що програма функціонує належним чином.
Загалом, підхід, заснований на подіях, є ефективним методом керування взаємодіями та робочими процесами в програмі, що робить його особливо придатним для додатків, які вимагають оперативності та взаємодії з користувачем.
Перетворення документів XPS і події
Коли вам потрібно змінити певну сторінку документа XPS за допомогою API Aspose.Page, ви зазвичай вибираєте активний документ (якщо у файлі 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 або зображення, процес відбувається по одній сторінці за раз. Коли завдання перетворення готується до обробки наступної сторінки, воно запускає подію «до сторінки». Користувач може визначити поведінку (обробку подій) для таких подій, розширивши клас BeforePageSavingEventHandler, таким чином використовуючи деякі з переваг, розглянутих у вступному розділі цієї статті.
Приклад додавання навігаційних гіперпосилань
У цьому розділі ми наведемо приклад навігаційних гіперпосилань. І щоб трохи ускладнити завдання, ми перетворимо лише підмножину всіх сторінок у PDF, як це визначено методом PdfSaveOptions.setPageNumbers()
.
Клас обробника подій
Нижче наведено розширення класу 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, абсолютний номер сторінки в усіх документах, відносний номер сторінки в поточному документі (який дорівнює попередній номер, якщо в пакеті лише один документ), і номер вихідної сторінки (який дорівнює абсолютному номеру сторінки, коли ми перетворюємо весь пакет).
Логіка наступних двох блоків if досить проста. Він аналізує аргумент події getOutputPageNumber()
, щоб опустити деякі посилання, де це необхідно: посилання [First]
і [Prev]
не буде додано до першої сторінки, тоді як [Next]
і [Останні]
посилання не відображатимуться на останній сторінці. Логіка також розроблена таким чином, щоб врахувати обидва сценарії, незалежно від того, чи вказано номери сторінок, чи ні.
Після блоків if є код, який додає номер сторінки в нижньому правому куті сторінки.
Останній рядок додає структурний запис сторінки, тобто елемент, який відображатиметься на панелі навігації програми перегляду PDF (якщо підтримується).
Код для конвертації
Тепер, коли обробник подій «перед сторінкою» визначено, ми можемо написати код для перетворення документа:
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()
.
Усе, що залишилося зробити зараз, це запустити перетворення у PDF за допомогою методу документа saveAsPdf()
.
Висновок
У цій статті ми розглянули фундаментальні аспекти подійного підходу в програмуванні, розглянули прямий метод зміни сторінок XPS-документа та дослідили вдосконалену техніку внесення повторюваних змін до всіх вихідних сторінок під час процесу перетворення. , використовуючи вставку навігаційних гіперпосилань як приклад.
Щоб отримати повні приклади, перегляньте наш Приклад проекту.