Статьи

Создание богатых клиентов с JacpFX и JavaFX2

Создание быстрых и масштабируемых настольных клиентов — это всегда непростая задача, особенно при работе с большим объемом данных и долгосрочными задачами. Хотя Eclipse RCP и Netbeans RCP являются признанными платформами, идея состояла в том, чтобы создать облегченную среду, которая обрабатывает компоненты асинхронно, подобно веб-компонентам. Разработчики должны меньше заниматься потоковыми темами и должны иметь возможность самостоятельно моделировать поток сообщений приложений. Эти и многие другие идеи привели к проекту JacpFX.

JacpFX

Проект JacpFX (Java Asynchronous Client Platform) — это платформа для создания Rich Client (Desktop и / или Web) в стиле MVC с использованием JavaFX 2 , Spring и Actor-подобного подхода. Он предоставляет простой API для создания рабочего пространства, перспектив и компонентов; общаться со всеми частями и легко составить клиентское приложение.

Что JacpFX предлагает вам?

  • Реализовать масштабирование и адаптировать Rich Client к небольшому и простому API (~ 120 Кб) в Java
    • Полностью интегрирован с Spring и JavaFX 2
  • Добавить / переместить / удалить определенные компоненты во время выполнения в вашем пользовательском интерфейсе
    • Создайте базовый макет в перспективе и определите «заполнители» для пользовательского интерфейса компонента.
  • Обработка компонентов вне потока приложения FX
    • Методы «handle» выполняются в рабочем потоке, а метод «posthandle» выполняется потоком приложения FX
  • Компоненты обратного вызова без учета состояния и состояния
    • Аутсорсинг длительных процессов и вычислений
  • Легко обрабатывать асинхронные процессы
    • Нет необходимости в явных потоках или таких вещах, как Runtime.invoke ()
  • Общаться через асинхронные сообщения
  • Нет общих данных между компонентами
  • Неизменные сообщения

Следующая статья даст вам краткое введение в JacpFX и о том, как создавать с его помощью Rich Clients на основе JavaFX 2. Показанный здесь пример клиента — это (псевдо) менеджер контактов, который вы можете попробовать здесь: http://developer.ahcp.de/demo/JACPFX2Demo.html ; Полный исходный код вы можете скачать здесь: http://code.google.com/p/jacp/downloads/list

Предварительно требования :

Для запуска демонстрационного приложения должна быть установлена ​​допустимая среда выполнения JavaFX2 (в настоящее время доступна только для Windows). Для компиляции прилагаемого демонстрационного кода предполагается установить JavaFX2 SDK (также доступный для Mac и Linux) и Apache Maven. Смотрите подробные инструкции в конце этой статьи:

Изображение 1: Выберите категорию в первый раз, и клиент попросит вас создать 250 000 контактов. Хотя эти контакты создаются и постепенно добавляются в представление таблицы, вы можете выбрать следующую категорию, перейти к следующей странице таблицы, просмотреть данные диаграммы потребителей или просто отредактировать контакт. Имейте в виду, что в коде демо-клиента не использовались явные потоки

Приложение — Структура

Приложение JacpFX состоит из модуля запуска приложений, рабочей среды, минимум одной перспективы и хотя бы одного компонента. В примере клиента используются три компонента UI и три компонента без обратного вызова (обратный вызов) для создания данных и имитации доступа к тяжелым данным.

Приложение — Launcher (AFX2SpringLauncher)

Приложение — средство запуска — это основной класс вашего приложения, в котором вы определяете контекст Spring. JacpFX-приложение использует декларацию xml для определения иерархии приложения и всех метаданных, таких как «идентификатор компонента» и «цель выполнения». Spring main.xml находится в каталоге ресурсов и будет объявлен в конструкторе средств запуска:

01
02
03
04
05
06
07
08
09
10
11
12
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public class ContactMain extends AFX2SpringLauncher {</span> открытый класс ContactMain расширяет AFX2SpringLauncher {</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public ContactMain() {</span> public ContactMain () {</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">super("main.xml");</span> супер ( "main.xml");</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public static void main(String[] args) {</span> public static void main (String [] args) {</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">Application.launch(args);</span> Application.launch (арг);</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@Override</span> @Override</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public void postInit(Stage stage) {</span> public void postInit (Stage stage) {</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// define your css and other config stuff here</span> // определить ваш CSS и другие вещи конфигурации здесь</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>

Листинг 1: средство запуска приложений

Приложение — Workbench (AFX2Workbench)

Рабочая среда является корневым узлом пользовательского интерфейса приложения JacpFX. Здесь вы настраиваете приложение, устанавливаете разрешение, определяете панели инструментов, меню и имеете ссылку на стадию JavaFX.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public class ContactWorkbench extends AFX2Workbench {</span> открытый класс ContactWorkbench расширяет AFX2Workbench {</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@Override</span> @Override</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public void handleInitialLayout(IAction<Event, Object> action,</span> public void handleInitialLayout (действие IAction <Event, Object>,</span>
            <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">IWorkbenchLayout<Node> layout, Stage stage) {</span> IWorkbenchLayout <Node> layout, Stage stage) {</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">layout.setWorkbenchXYSize(1024, 768);</span> layout.setWorkbenchXYSize (1024, 768);</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">layout.registerToolBar(ToolbarPosition.NORTH);</span> layout.registerToolBar (ToolbarPosition.NORTH);</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">layout.setMenuEnabled(true);</span> layout.setMenuEnabled (истина);</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>
 
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@Override</span> @Override</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public void postHandle(FX2ComponentLayout layout) {</span> public void postHandle (макет FX2ComponentLayout) {</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">final MenuBar menu = layout.getMenu();</span> окончательное MenuBar menu = layout.getMenu ();</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">final Menu menuFile = new Menu("File");</span> окончательное меню menuFile = новое меню («Файл»);</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">final MenuItem itemHelp = new MenuItem("Help");</span> окончательный MenuItem itemHelp = новый MenuItem («Справка»);</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">/// add the event listener and show an option-pane with some help text</span> /// добавляем прослушиватель событий и показываем панель параметров с текстом справки</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">menuFile.getItems().add(itemHelp);</span> . MenuFile.getItems () добавить (itemHelp);</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">menu.getMenus().addAll(menuFile);</span> . Menu.getMenus () addAll (menuFile);</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>

Листинг 2: Рабочая среда

Перспектива (AFX2Perspective)

Задача перспективы состоит в том, чтобы предоставить компоновку текущего представления и зарегистрировать корневой и все конечные узлы представления. Конечные узлы являются «целью выполнения» (контейнером) для всех компонентов, связанных (внедренных) с этой перспективой. Демо-перспектива в основном определяет две SplitPanes и регистрирует их как «target-target» для отображения содержимого ContactTreeView слева; ContactTableView вверху справа и ContactChartView внизу справа.

Рисунок 2: Три цели, определенные перспективой в демонстрации
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public class ContactPerspective extends AFX2Perspective {</span> открытый класс ContactPerspective расширяет AFX2Perspective {</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@Override</span> @Override</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public void onStartPerspective(FX2ComponentLayout layout) {</span> public void onStartPerspective (макет FX2ComponentLayout) {</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// create button in toolbar;</span> // создать кнопку на панели инструментов;</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">button should switch top and bottom id's</span> кнопка должна переключать верхний и нижний идентификаторы</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">ToolBar north = layout</span> Панель инструментов север = макет</span>
                <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">.getRegisteredToolBar(ToolbarPosition.NORTH);</span> .getRegisteredToolBar (ToolbarPosition.NORTH);</span>
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">...</span> ...</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">north.getItems().add(new Button("switch view");) ;</span> north.getItems (). add (new Button ("switch view"););</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>
 
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@Override</span> @Override</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public void onTearDownPerspective(FX2ComponentLayout layout) { }</span> public void onTearDownPerspective (макет FX2ComponentLayout) {}</span>
 
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@Override</span> @Override</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public void handlePerspective(IAction<Event, Object> action,</span> public void handlePerspective (действие IAction <Event, Object>,</span>
            <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">FX2PerspectiveLayout perspectiveLayout) {</span> FX2PerspectiveLayoutpectiveLayout) {</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">if (action.getLastMessage().equals(MessageUtil.INIT)) {</span> if (action.getLastMessage (). equals (MessageUtil.INIT)) {</span>
            <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">createPerspectiveLayout(perspectiveLayout);</span> createPerspectiveLayout (perspectiveLayout);</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>    
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">private void createPerspectiveLayout(FX2PerspectiveLayout perspectiveLayout) {</span> private void createPerspectiveLayout (FX2PerspectiveLayout visionLayout) {</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">//// define your UI layout</span> //// определить ваш макет интерфейса</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">...</span> ...</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// Register root component</span> // Зарегистрируем корневой компонент</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">perspectiveLayout.registerRootComponent(mainLayout);</span> perspectiveLayout.registerRootComponent (mainLayout);</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// register left menu</span> // зарегистрируем левое меню</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">perspectiveLayout.registerTargetLayoutComponent("PleftMenu", leftMenu);</span> pectiveLayout.registerTargetLayoutComponent ("PleftMenu", leftMenu);</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// register main content Top</span> // зарегистрируем основное содержание</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">perspectiveLayout.registerTargetLayoutComponent(“PmainContentTop”,</span> perspectiveLayout.registerTargetLayoutComponent ( «PmainContentTop»,</span>
                        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">mainContentTop);</span> mainContentTop);</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// register main content Bottom</span> // регистрация основного контента Bottom</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">perspectiveLayout.registerTargetLayoutComponent("PmainContentBottom",</span> perspectiveLayout.registerTargetLayoutComponent ( "PmainContentBottom",</span>
                <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">mainContentBottom);</span> mainContentBottom);</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>
 
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>

Листинг 3: Перспектива

UI-Компоненты (AFX2Component)

AFX2Components — это фактические компоненты пользовательского интерфейса в приложении JacpFX, которые отображаются как компоненты JavaFX. Демонстрация определяет левый ( ContactTreeView ), главный-верхний ( ContactTableView ) и главный-нижний ( ContactDemoChartView ) AFX2Component . Компонент JacpFX имеет четыре метода для реализации; «OnStartComponent» и «onTearDownComponent», а также «handleAction» и «postHandleAction». Пока «handleAction» выполняется в рабочем потоке, «postHandle» запускается в потоке приложения FX .

Изображение 3: Компонентный жизненный цикл компонента AFX2

Вы можете использовать ленивую инициализацию компонентов и выключить или перезапустить компоненты, если хотите.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public class ContactTreeView extends AFX2Component {</span> открытый класс ContactTreeView расширяет AFX2Component {</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">private ObservableList<Contact> contactList;</span> private ObservableList <Контакт> contactList;</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">...</span> ...</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@Override</span> @Override</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public Node handleAction(final IAction<Event, Object> action) {</span> public Node handleAction (конечное действие IAction <Event, Object>) {</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">if (action.getLastMessage().equals(MessageUtil.INIT)) {</span> if (action.getLastMessage (). equals (MessageUtil.INIT)) {</span>
           <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">this.pane = new ScrollPane();</span> this.pane = new ScrollPane ();</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">...</span> ...</span>
         <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">return this.pane;</span> вернуть this.pane;</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">return null;</span> вернуть ноль;</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>
 
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@Override</span> @Override</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public Node postHandleAction(final Node node,</span> public Node postHandleAction (конечный узел Node,</span>
            <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">final IAction<Event, Object> action) {</span> окончательное действие IAction <Event, Object>) {</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">if (action.getLastMessage() instanceof Contact) {</span> if (action.getLastMessage () instanceof Contact) {</span>
            <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">this.contactList.addAll((Contact) action.getLastMessage());</span> this.contactList.addAll ((Контакт) action.getLastMessage ());</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">return this.pane;</span> вернуть this.pane;</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>
 
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@Override</span> @Override</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public void onStartComponent(final FX2ComponentLayout layout) {</span> public void onStartComponent (окончательный макет FX2ComponentLayout) {</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">final ToolBar north = layout</span> окончательная панель инструментов север = макет</span>
                <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">.getRegisteredToolBar(ToolbarPosition.NORTH);</span> .getRegisteredToolBar (ToolbarPosition.NORTH);</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">…</span> ...</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">north.add(new Button("add category"));</span> north.add (новая кнопка («добавить категорию»));</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>
    
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@Override</span> @Override</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public void onTearDownComponent(final FX2ComponentLayout layout) { }</span> public void onTearDownComponent (окончательный макет FX2ComponentLayout) {}</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">...</span> ...</span>   
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>

Листинг 4: ContactTreeView (вид слева)

Метод handleAction в листинге 4 используется для инициализации пользовательского интерфейса компонента. В акции «postHandle» демо были добавлены новые контакты; contactList привязан к существующему TreeView, поэтому вы не можете обновить его вне потока приложения FX и поэтому должны использовать метод «postHandle».

Компоненты обратного вызова

Компоненты обратного вызова JacpFX не являются компонентами UI / службы. Подобно AFX2Component , у них есть метод с именем «handle», который выполняется в рабочем потоке. Результатом может быть объект любого типа, и он будет автоматически доставлен обратно в вызывающий компонент или перенаправлен в любой другой компонент.

В этих типах компонентов вы выполняете долгосрочные задачи, вызываете сервисные вызовы или просто извлекаете данные из хранилища. JacpFX предоставляет два типа компонентов обратного вызова: « AStatelessCallbackComponent » и (с сохранением состояния) « ACallbackComponent ». Демо-клиент использует компонент « ACallbackComponent » для генерации случайных данных диаграммы для выбранного контакта в таблице.

Для генерации большого количества контактов задействованы два « AStatelessCallbackComponents ». Один компонент делит общую сумму на куски, а второй просто создает контакты. Результат будет отправлен непосредственно в компонент пользовательского интерфейса и добавлен в таблицу.

обмен сообщениями

Обмен сообщениями является основой JacpFX Framework. JacpFX использует асинхронный обмен сообщениями для уведомления компонентов и перспектив вашего приложения.

Поток сообщений для создания начального объема данных для категории в демонстрационном приложении выглядит следующим образом:

Рисунок 4: Поток сообщений для создания начального объема данных в демонстрационном приложении

Состояние компонента JacpFX всегда изменяется сообщениями. Если задача должна быть обработана в фоновом потоке, вы просто отправляете сообщение компоненту и обрабатываете работу методом «handle». Результат может быть отправлен обратно в компонент вызывающей стороны или обработан потоком приложения FX в методе «postHandle» (в случае компонентов пользовательского интерфейса). Вы всегда должны избегать выполнения длительных задач в потоке приложения FX; вместо этого вызовите вашу сервисную или DB-операцию внутри метода «handle».

JacpFX отличается между двумя типами сообщений: локальным и глобальным .

Локальные сообщения

Для запуска локального сообщения просто получите прослушиватель

1
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">IActionListener<EventHandler<Event>, Event, Object> listener = this.getActionListener(“message”);</span> IActionListener <EventHandler <Event>, Event, Object> listener = this.getActionListener («message»);</span>

только с одним аргументом — само сообщение. Этот слушатель может быть назначен любому JavaFX eventHandler (например, onMouseEvent и т. Д.) Или его можно запустить, вызвав

1
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">listener.performAction(event);</span> listener.performAction (событие);</span>

Глобальные сообщения

С глобальными сообщениями вы общаетесь с другими зарегистрированными компонентами. Компоненты обратного вызова отвечают на сообщение по умолчанию, поэтому вам не нужно явно создавать ответное сообщение — вы также можете это сделать. Обмен сообщениями является предпочтительным способом обмена данными между компонентами и запуска задач. Подобно локальным сообщениям, вы создаете экземпляр слушателя, но с явным идентификатором цели:

1
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">IActionListener<EventHandler<Event>, Event, Object> listener = this.getActionListener(“id“,“message”);</span> IActionListener <EventHandler <Event>, Event, Object> listener = this.getActionListener («id», «message»);</span>

Создайте демонстрационное приложение из исходного кода

Зарегистрируйте JavaFX в вашем локальном репозитории Maven

Все JacpFX-проекты являются проектами Maven и требуют JavaFX 2 (jfxrt.jar). Некоторые включают JavaFX 2 в качестве системной зависимости, но мы предпочли зарегистрировать jfxrt.jar в локальном репозитории. Для создания развертываемых файлов (jnlp и html) вам дополнительно необходимо зарегистрировать Java-задачи Ant-Tasks (ant-javafx.jar). Для этого перейдите в $ {SDK-home} / rt / lib и введите:

1
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">mvn install:install-file -Dfile=jfxrt.jar -DgroupId=com.oracle -DartifactId=javafx-runtime -Dpackaging=jar -Dversion=2.0</span> mvn install: install-file -Dfile = jfxrt.jar -DgroupId = com.oracle -DartifactId = javafx-runtime -Dpackaging = jar -Dversion = 2.0</span>

Затем скопируйте каталог «bin» (в linux i386) в вашу папку .m2 \ repository \ com \ oracle \ javafx-runtime . Затем перейдите в каталог $ {SDK-home} / tools и введите:

1
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">mvn install:install-file -Dfile=ant-javafx.jar -DgroupId=com.oracle -DartifactId=ant-javafx -Dpackaging=jar -Dversion=2.0</span> mvn install: install-file -Dfile = ant-javafx.jar -DgroupId = com.oracle -DartifactId = ant-javafx -Dpackaging = jar -Dversion = 2.0</span>

Построить проект

Чтобы собрать проект, просто разархивируйте папку проекта и введите mvn package . Файлы jar, jnlp и html создаются в каталоге $ {projectHome} / target / deploy . Чтобы создать проект Eclipse, просто введите mvn eclipse: eclipse .

Что будет дальше?

JacpFX в настоящее время в версии 1.0; после многих лет создания прототипов с Echo3 и Swing, JacpFX является первым стабильным выпуском, основанным на JavaFX 2 и определенным планом выпуска. Вы можете найти подробную документацию на вики-странице проектов ( http://code.google.com/p/jacp/wiki/Documentation ). Наш план выпуска (также расположенный на вики) определяет версию 1.1 в июне этого года. Основными изменениями будут поддержка аннотаций и официальная поддержка FXML (также вы уже можете использовать FXML). Обратная связь всегда приветствуется, поэтому не стесняйтесь обращаться к нам.

Справка: Создание богатых клиентов с помощью JacpFX и JavaFX2 от нашего партнера по W4G Энди Мончека .