Статьи

JacpFX и DataFX-потоки, идеально подходящие для JavaFX


JacpFX — это инфраструктура RCP, основанная на JavaFX, которая помогает разработчикам структурировать приложение со слабосвязанными, повторно используемыми компонентами, а DataFX-flow — это API, который позволяет определять потоки между контроллерами и представлениями в JavaFX.

Оба проекта разрабатывались независимо, и пока я разрабатывал приложение JacpFX, я осознал отсутствие поддержки потоков. Интеграция простого потока DataFX в JacpFX была довольно простой, компонент JacpFX представляет собой контроллер с представлением FXML или простым представлением JavaFX; с другой стороны, FlowHandler потока DataFX возвращает StackPane, который легко интегрировать в текущее представление. Недостатком этого простого решения является изоляция контекста вашего потока DataFX от контекста JacpFX, что означает, что они не имеют прямого доступа друг к другу.

В JavaOne у меня была возможность провести час с Хендриком Эбберсом (одним из коммиттеров DataFX) и создать для этого решение.
Получающийся плагин JacpFX / DataFX-flow позволяет вам внедрять контекст JacpFX определенного компонента в контроллеры потока DataFX. Это позволяет контроллерам потока DataFX взаимодействовать через шину сообщений JacpFX с остальной частью приложения JacpFX. Помимо этого, контроллер потока DataFX получает доступ к пакетам ресурсов и другим методам / ресурсам компонента JacpFX.


Чтобы продемонстрировать использование обеих платформ, я создал простой пример приложения, основанный на следующих шагах:

Создайте приложение JacpFX из архетипа:

JacpFX предоставляет простой архетип с двумя примерами перспективы (представление FXML + JavaFX) и двумя компонентами, повторно используемыми в обеих перспективах. Для создания базового приложения JacpFX используйте простой архетип:

mvn archetype:generate  -DarchetypeGroupId=org.jacpfx  -DarchetypeArtifactId=JacpFX-simple-quickstart  -DarchetypeVersion=2.0.2

Для интеграции плагина DataFX-flow добавьте следующую зависимость к вашему pom:

  	<dependency>
            <groupId>org.jacpfx</groupId>
            <artifactId>jacpfx.JavaFXDataFXPlugin</artifactId>
            <version>1.0</version>
            <scope>compile</scope>
        </dependency>

Создать простой поток между двумя контроллерами потока DataFX

Теперь мы создаем два контроллера потока DataFX, WizardStartController и Wizard1Controller. Wizard1Controller будет содержать контекст JacpFX и включать текстовое поле, ввод текста будет отправляться через сообщения в компонент JacpFX. Контроллер будет выглядеть так:

@FXMLController(value="/fxml/wizard1.fxml", title = "Wizard: Step 1")
public class Wizard1Controller {

    @FXML
    @ActionTrigger("back")
    private Button backButton;

    @FXML
    @ActionTrigger("next")
    private Button nextButton;

	/**
	** The JacpFX context
	**/
    @Resource
    private Context context;


    @FXML
    private TextField name;


    @PostConstruct
    public void init() {
        nextButton.setDisable(true);
        name.setOnKeyReleased(event->{
            context.send(BasicConfig.COMPONENT_BOTTOM, name.getText());
		});
    }

}

Интегрировать поток DataFX в компонент JacpFX


Чтобы иметь возможность внедрить контекст JacpFX в контроллер
потока DataFX, я создал потоковую
оболочку DataFX, которая дополнительно принимает идентификатор компонента JacpFX, контекст которого должен быть введен. Использование
потока DataFX
точно такое же, поэтому мы создаем
FlowHandler и получаем корневой узел потока DataFX при запуске
FlowHandler . Корневой узел теперь может быть включен в ваше представление компонентов JacpFX.
@View(id = BasicConfig.COMPONENT_TOP,
        name = "SimpleView",
        resourceBundleLocation = "bundles.languageBundle",
        initialTargetLayoutId = BasicConfig.TARGET_CONTAINER_TOP)
public class ComponentLeft implements FXComponent {
    private Node pane;
    @Resource
    private Context context;

    @Override
    public Node handle(final Message<Event, Object> message) {
        // runs in worker thread
        return null;
    }

    @Override
    public Node postHandle(final Node arg0,
                           final Message<Event, Object> message) {
        // runs in FX application thread
        return this.pane;
    }

    @PostConstruct
    public void onPostConstructComponent(final FXComponentLayout arg0,
                                         final ResourceBundle resourceBundle) {
        this.pane = createUI();
    }


    private Node createUI() {
        final VBox main = new VBox();
        Flow flow = new DataFXFlowWrapper(WizardStartController.class,BasicConfig.COMPONENT_TOP).
                withLink(WizardStartController.class, "next", Wizard1Controller.class).
                withGlobalBackAction("back");
        FlowHandler flowHandler = flow.createHandler();
        StackPane pane = null;
        try {
            pane = flowHandler.start(new AnimatedFlowContainer(Duration.millis(320), ContainerAnimations.ZOOM_IN));
			main.getChildren().add(pane);
        } catch (FlowException e) {
            e.printStackTrace();
        }

        return main;
    }


}

Для запуска JacpFX и DataFX-потока требуется Java 8 / JavaFX 8, упакованный jar можно скачать здесь:  http://jacpfx.org/data/SimpleDataFX_JacpFX.jar  , просто выполните: 

java -jar SimpleDataFX_JacpFX.jar

Источник этого примера приложения можно найти здесь:

Основные сведения о потоке данных можно найти в блоге Хендрика здесь:
http://www.guigarage.com/2014/05/datafx-8-0-tutorials/
 

Домашняя страница JacpFX со всей документацией — 
http://jacpfx.org