2013-10-13 88 views
17

我一直在看一些博客和其他stackoverflow的問題,我沒有看到我的問題的直接答案。我正在創建一個javafx gui客戶端,我想讓我的菜單欄成爲一個fxml中的一個控制器,然後我希望內容區域成爲額外的fxml文件。登錄屏幕將是一個fxml,登錄屏幕將成爲應用程序的主要內容,並且將在一個fxml中。我如何去做這件事?如何用不同的fxml文件創建多個javafx控制器?

我只是不希望有我所有的代碼爲我登錄,菜單欄,並在同一個文件的主要內容。這是我工作的一個形象:

enter image description here

+3

一些[示例代碼]使用的概念從一些(https://gist.github.com/jewelsea/6460130)這個問題的答案。 – jewelsea

+0

另一個例子在這裏:[鏈接](http://stackoverflow.com/questions/19435384/how-to-bind-controls-across-two-fxml-from-the-main-controller) – Dil

回答

24

使用FXML通過使用自定義的Java類作爲FX成分:根和FX:你FXML文件的控制器:http://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm

要做到這一點,你需要在你自定義的Java類FXMLLoader的構造函數調用這會加載你的FXML。 的好處是改變FXML加載組件的方式。

的經典方法通過FXMLLoader具有嵌套控制器實例化的組件是:FXML第一,則控制器爲每個部分。

利用該技術是這樣的:控制器首先,然後FXML每個組件。並且您不會直接在FXML中加載FXML,您將在FXML中導入自定義Java類。

這是一個更好的抽象(沒必要知道,當你在FXML導入組件是如何實現的),並幫助重用代碼,因爲它是像實現與FXML支持自定義窗口小部件。爲了讓你的組件可重用,確保你的實現沒有與其他組件緊密耦合,或者使用IOC來實現(例如,Spring與JavaFX集成)。通過這種方式,您將能夠在應用程序的任何部分導入組件(就像DateInput小部件一樣),無需擔心,並且不會重複代碼。

在你的情況,你將有:

public class MenuBox extends VBox { 

@FXML 
private LoginBox loginBox; 

@FXML 
private ProfilesBox profilesBox; 

public MenuBox() { 
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("menu.fxml")); 
    fxmlLoader.setRoot(this); 
    fxmlLoader.setController(this); 
    try { 
     fxmlLoader.load(); 
    } catch (IOException exception) { 
     throw new RuntimeException(exception); 
    } 
} 

public class LoginBox extends VBox { 
public LoginBox() { 
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("login.fxml")); 
    fxmlLoader.setRoot(this); 
    fxmlLoader.setController(this); 
    try { 
     fxmlLoader.load(); 
    } catch (IOException exception) { 
     throw new RuntimeException(exception); 
    } 
} 

public class ProfilesBox extends VBox { 
public ProfilesBox() { 
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("profiles.fxml")); 
    fxmlLoader.setRoot(this); 
    fxmlLoader.setController(this); 
    try { 
     fxmlLoader.load(); 
    } catch (IOException exception) { 
     throw new RuntimeException(exception); 
    } 
} 

你將導入LoginBox和ProfilesBox在管理全球佈局的頁面menu.fxml:

<?import com.foo.bar.LoginBox ?> 
<?import com.foo.bar.ProfilesBox ?> 
<fx:root type="javafx.scene.layout.VBox" 
    xmlns:fx="http://javafx.com/fxml"> 

<!-- Stuff here to declare the menu bar--> 

    <HBox> 
     <ProfilesBox fx:id="profilesBox"/> 
     <LoginBox fx:id="loginBox"/> 
    </HBox> 

</fx:root> 

login.fxml和型材.fxml只包含基本組件。

+0

我有點理解你的說法,我只是不認爲我能看到全貌。你有更詳細的例子嗎? –

+0

可以創建自己的小部件(即ProfilesBox&LoginBox)並將它們放在fxml文件中嗎?那麼login.fxml和profiles.fxml是什麼樣的? –

+1

要添加到已經很好的示例中,只需確保將自定義控件導入FXML。例如。 <?import com.foo.bar.LoginBox?>。 – chooks

4
  1. 可以include FXML documents一個在另一個內 - 這應該幫助你分離的設計邏輯

  2. 這意味着你可以有Nested Controllers - 每個文檔一個。

從文檔中,您現在可以設置您的代碼,以便邏輯可以分開以及從根控制器調用(如果需要的話)。

希望有所幫助。

+2

我看了嵌套控制器文檔,如果我可以看到包含fxml中的內容,主控制器初始化方法的內容以及對話框控制器的外觀,我認爲這會非常有幫助。我只是不明白細節是如何工作的。 –

0

我需要具有類似要求(在節點的更多控制和佈局)的彈出窗口。

已經通過建議的工作我的方式,我發現可能是有用的解決方案。首先,我創建了第二個fxml文檔和第二個控制器(在NetBeans中,New - > Empty FXML ... - > Use Java Controller - > Create New ...)。

一個小挑戰是如何在主控制器中構建舞臺並將其連接到彈出控制器。

鏈接Passing Parameters JavaFX FXML給出了一些真正的好洞見和技巧。

最終代碼看起來像這樣(我希望它可以幫助別人):

// Anchor Pane from the popup 
@FXML 
AnchorPane anchorPanePopup; 

@FXML 
private void soneButtonAction(ActionEvent event) throws IOException {  
    Stage newStage = new Stage(); 
    AnchorPane anchorPanePopup = (AnchorPane) FXMLLoader.load(getClass().getResource("Popup_FXML.fxml")); 
    Scene scene = new Scene(anchorPanePopup); 
    newStage.setScene(scene); 
    newStage.initModality(Modality.APPLICATION_MODAL); 
    newStage.setTitle("Dialog Window"); 
    newStage.showAndWait();   
} 
相關問題