使用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