使用JacpFX和JavaFX2构建富客户端

创建快速且可扩展的桌面客户端始终是一个挑战,特别是在处理大量数据和长时间运行的任务时。 尽管Eclipse RCP和Netbeans RCP是已建立的平台,但其想法是建立一个轻量级的框架来异步处理组件,类似于Web组件。 开发人员在线程主题上的工作应较少,并且应该能够自己对应用程序的消息流进行建模。 这些以及许多其他想法产生了JacpFX项目。

JacpFX

JacpFX(Java异步客户端平台)项目是一个框架,可使用JavaFX 2Spring和类似于Actor的组件方法以MVC样式创建Rich Client (桌面和/或Web)。 它提供了一个简单的API,用于创建工作区,透视图和组件。 与所有部分进行通信并轻松组成您的客户应用程序。

JacpFX为您提供什么?

  • 使用Java中的小型和简单API (〜120Kb)实现扩展和响应式Rich Clients
    • 与Spring和JavaFX 2完全集成
  • 在运行时在用户界面中添加/移动/删除定义的组件
    • 在Perspectives中创建基本布局,并为组件UI定义“占位符”
  • 在FX应用程序线程之外处理组件
    • “ handle”方法在工作线程中执行,“ posthandle”方法由FX应用程序线程执行
  • 有状态和无状态回调非UI组件
    • 外包长期运行的流程和计算
  • 轻松处理异步过程
    • 不需要显式线程或类似Runtime.invoke()的东西
  • 通过异步消息进行通信
  • 组件之间没有共享数据
  • 不变的讯息

以下文章将为您简要介绍JacpFX以及如何使用它创建基于JavaFX 2的Rich Clients。 这里显示的示例客户端是一个(伪)联系人管理器,您可以在这里尝试: 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组件和三个非UI(回调)组件来创建数据并模拟大量数据访问。

应用程序–启动器(AFX2SpringLauncher)

应用程序-启动器是定义Spring上下文的应用程序的主类。 JacpFX –应用程序使用xml声明来定义应用程序和所有元数据的层次结构,例如“ component-id”和“ execution-target”。 Spring main.xml位于资源目​​录中,并将在启动程序构造函数中声明:

public class ContactMain extends AFX2SpringLauncher {
    public ContactMain() {
        super("main.xml");
    }
    public static void main(String[] args) {
        Application.launch(args);
    }
    @Override
    public void postInit(Stage stage) {
        // define your css and other config stuff here
    }
}

清单1:应用程序启动器

应用程序–工作台(AFX2Workbench)

工作台是JacpFX应用程序的UI根节点。 在这里,您可以配置应用程序,设置分辨率,定义工具–条,菜单,并参考JavaFX阶段。

public class ContactWorkbench extends AFX2Workbench {
    @Override
    public void handleInitialLayout(IAction<Event, Object> action,
            IWorkbenchLayout<Node> layout, Stage stage) {
        layout.setWorkbenchXYSize(1024, 768);
        layout.registerToolBar(ToolbarPosition.NORTH);
        layout.setMenuEnabled(true);
    }

    @Override
    public void postHandle(FX2ComponentLayout layout) {
        final MenuBar menu = layout.getMenu();
        final Menu menuFile = new Menu("File");
        final MenuItem itemHelp = new MenuItem("Help");
        /// add the event listener and show an option-pane with some help text
        menuFile.getItems().add(itemHelp);
        menu.getMenus().addAll(menuFile);    }
}

清单2:工作台

透视图(AFX2Perspective)

透视图的任务是提供当前视图的布局,并注册视图的根节点和所有叶节点。 叶节点是与此透视图关联(注入)的所有组件的“执行目标”(容器)。 演示透视图基本上定义了两个SplitPanes ,并将它们注册为“执行目标”,以在左侧显示ContactTreeView的内容。 右上方的ContactTableView和右下方的ContactChartView

图2:演示中的透视图定义的三个目标
public class ContactPerspective extends AFX2Perspective {
    @Override
    public void onStartPerspective(FX2ComponentLayout layout) {
    // create button in toolbar; button should switch top and bottom id's 
        ToolBar north = layout
                .getRegisteredToolBar(ToolbarPosition.NORTH);
...
        north.getItems().add(new Button("switch view");) ;
    }

    @Override
    public void onTearDownPerspective(FX2ComponentLayout layout) {   }

    @Override
    public void handlePerspective(IAction<Event, Object> action,
            FX2PerspectiveLayout perspectiveLayout) {
        if (action.getLastMessage().equals(MessageUtil.INIT)) {
            createPerspectiveLayout(perspectiveLayout);
        }     
}
    private void createPerspectiveLayout(FX2PerspectiveLayout perspectiveLayout) {
        //// define your UI layout
        ...
        // Register root component
        perspectiveLayout.registerRootComponent(mainLayout);
        // register left menu
        perspectiveLayout.registerTargetLayoutComponent("PleftMenu", leftMenu);
        // register main content Top
        perspectiveLayout.registerTargetLayoutComponent(“PmainContentTop”,
                        mainContentTop);
        // register main content Bottom
        perspectiveLayout.registerTargetLayoutComponent("PmainContentBottom",
                mainContentBottom);
    }

}

清单3:透视图

UI组件(AFX2Component)

AFX2Components是JacpFX应用程序中实际的UI组件,它们呈现为JavaFX组件。 该演示定义了左侧( ContactTreeView ),主顶部( ContactTableView )和主底部( ContactDemoChartViewAFX2Component JacpFX组件有四种实现方法: “ onStartComponent”和“ onTearDownComponent”以及“ handleAction”和“ postHandleAction”。 工作线程中执行“ handleAction”时,在FX应用程序线程中运行“ postHandle”。

图3:AFX2Component的组件生命周期

您可以根据需要使用组件的延迟初始化以及关闭或重新启动组件。

public class ContactTreeView extends AFX2Component {
    private ObservableList<Contact> contactList;
    ...
    @Override
    public Node handleAction(final IAction<Event, Object> action) {
        if (action.getLastMessage().equals(MessageUtil.INIT)) {
           this.pane = new ScrollPane();        ...
         return this.pane;
        }
        return null;
    }

    @Override
    public Node postHandleAction(final Node node,
            final IAction<Event, Object> action) {
        if (action.getLastMessage() instanceof Contact) {
            this.contactList.addAll((Contact) action.getLastMessage());
        }
        return this.pane;
    }

    @Override
    public void onStartComponent(final FX2ComponentLayout layout) {
        final ToolBar north = layout
                .getRegisteredToolBar(ToolbarPosition.NORTH);
       …
        north.add(new Button("add category"));
    }
   
    @Override
    public void onTearDownComponent(final FX2ComponentLayout layout) {    }
    ...    
}

清单4:ContactTreeView(左视图)

清单4中的“ handleAction”方法用于初始化组件UI。 在演示的“ postHandle”操作中,添加了新联系人; contactList已绑定到现有的TreeView,因此您无法在FX应用程序线程之外对其进行更新,因此必须使用“ postHandle”方法。

回调组件

JacpFX回调组件是非UI /服务组件。 AFX2Component相似,它们具有一种称为“处理”的方法,该方法在工作线程中执行。 结果可以是任何类型的对象,并将自动传递回调用组件或重定向到任何其他组件。

在这些类型的组件中,您将执行长时间运行的任务,调用服务调用或仅从存储中检索数据。 JacpFX提供两种类型的回调组件,“ AStatelessCallbackComponent ”和(有状态的)“ ACallbackComponent ”。 演示客户端使用“ ACallbackComponent ”组件为选定的联系人表生成随机图表数据。

为了生成大量联系人,需要使用两个“ AStatelessCallbackComponents ”。 其中一个组件将总金额分成大块,第二个组件仅创建联系人。 结果将直接发送到UI组件并添加到表中。

讯息传递

消息传递是JacpFX框架的本质。 JacpFX使用异步消息传递来通知应用程序的组件和观点。

在演示应用程序中为类别创建初始数据量的消息流如下所示:

图4:在演示应用程序中创建初始数据量的消息流

JacpFX组件的状态始终由消息更改。 如果应该在后台线程中处理任务,则只需向组件发送一条消息,然后使用“ handle”方法处理工作。 结果可以发送回调用方组件,或由FX应用程序线程在“ postHandle”方法中进行处理(对于UI组件)。 您应始终避免在FX应用程序线程上执行长时间运行的任务; 而是在“ handle”方法中调用您的服务或数据库操作。

JacpFX在两种消息类型( 本地消息和全局消息)之间有所不同。

本地留言

要触发本地消息,只需获取一个侦听器

IActionListener<EventHandler<Event>, Event, Object> listener =   this.getActionListener(“message”);

仅带有一个参数–消息本身。 可以将此侦听器分配给任何JavaFX eventHandler(例如onMouseEvent等),也可以通过调用将其触发

listener.performAction(event);

全局消息

通过全局消息,您可以与其他已注册组件通信。 默认情况下,回调组件会响应消息,因此您无需显式创建响应消息-也可以。 消息传递是在组件之间交换数据和触发任务的首选方式。 与本地消息类似,您可以创建一个侦听器实例,但具有明确的目标ID:

IActionListener<EventHandler<Event>, Event, Object> listener =   this.getActionListener(“id“,“message”);

从源代码构建演示应用程序

在本地Maven存储库中注册JavaFX

所有JacpFX-Projects都是Maven项目,并且需要JavaFX 2(jfxrt.jar)。 其中一些包含JavaFX 2作为系统依赖项,但是我们更愿意在本地存储库中注册jfxrt.jar。 要创建可部署文件(jnlp和html),您还需要注册JavaFX Ant-Tasks(ant-javafx.jar)。 为此,请更改您的$ {SDK-home} / rt / lib并输入:

mvn install:install-file -Dfile=jfxrt.jar -DgroupId=com.oracle -DartifactId=javafx-runtime -Dpackaging=jar -Dversion=2.0

然后将“ bin”目录(在Linux i386上)复制到您的.m2 \ repository \ com \ oracle \ javafx-runtime文件夹中。 接下来转到$ {SDK-home} / tools目录,然后键入:

mvn install:install-file -Dfile=ant-javafx.jar -DgroupId=com.oracle -DartifactId=ant-javafx -Dpackaging=jar -Dversion=2.0

建立项目

要构建项目,只需解压缩项目文件夹并键入mvn package jar,jnlp和html文件在$ {projectHome} / target / deploy中创建 要创建Eclipse项目,只需键入mvn eclipse:eclipse

接下来会发生什么?

JacpFX当前是1.0版; 在使用Echo3和Swing进行了多年的原型设计之后,JacpFX是基于JavaFX 2和已定义的发布计划的第一个稳定版本。 您可以在项目Wiki页面( http://code.google.com/p/jacp/wiki/Documentation )上找到详细的文档。 我们的发布计划(也位于Wiki上)在今年6月定义了1.1版。 主要的变化将是注释支持和官方的FXML支持(您也已经可以使用FXML)。 随时欢迎您提供反馈,请随时与我们联系。

参考: W4G合作伙伴 Andy Moncsek的 JacpFX和JavaFX2构建富客户端

翻译自: https://www.javacodegeeks.com/2012/03/building-rich-clients-with-jacpfx-and.html