2016-12-08 153 views
0

我有一個類,它調用超級構造函數。超類加載的FXML封裝佈局,然後另一FXML佈局作爲包裝中的一個元素的子元素,像這樣:JavaFx嵌套控制器?

// Reference 'outer' FXML 
URL outer_url = getClass().getResource("/main/resources/fxml/RootNode.fxml"); 
FXMLLoader outer_loader = new FXMLLoader(outer_url); 
outer_loader.setRoot(this); 
outer_loader.setController(this); 

// Reference 'inner' FXML 
URL inner_url = getClass().getResource(fxml_path); 
FXMLLoader inner_loader = new FXMLLoader(inner_url); 

try { 
    outer_loader.load(); 

    /* The root of inner_loader is a component of outer_loader FXML, 
    * thus outer_loader.load() must be called first. */ 
    inner_loader.setRoot(outer_loader.getNamespace().get("vbox_center")); 
    inner_loader.setController(controller); 
    inner_loader.load(); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

我需要的類是inner_loader的控制器。這可能嗎?我試圖通過超級構造函數傳遞給該類的引用,但是在超級構造函數被調用之前我無法引用'this'。

任何想法?提前致謝。

編輯:我也試過直接通過內部FXML文件指定控制器,但是這造成了問題。編輯2:我忘了指定,加載兩個FXML佈局的超類由多個節點繼承,這就是爲什麼我不能只創建一個Controller的實例並將其直接傳遞給inner_loader。我需要(以某種方式)將實例引用傳遞給超類,並將其用作控制器。

+0

的重複:[了JavaFx嵌套連續滾筒(FXML )](http://stackoverflow.com/questions/12543487/javafx-nested-controllers-fxml-include)? – jewelsea

+0

我的確看到了這個問題 - 與我的區別在於加載FXML的超類由多個不同的節點繼承,因此需要將實例引用傳遞給它 - 我不能每次都創建一個新實例。 – user3668541

+0

「我需要將實例引用傳遞給超類」:我不太明白你的意思。當前對象('this')當然是它自己類的一個實例,因此也是超類。你可以傳遞'this',這會很奇怪,因爲你將爲兩個不同的FXML文件使用與控制器相同的對象,並且'initialize()'方法(如果有的話)會被調用兩次。 –

回答

1

這並不完全清楚你想要做什麼,但它看起來像你試圖使用繼承和FXML-based custom components來創建一個專業化的模板。

這是可能的。您可以按照通常的方式在構造函數中加載FXML。因爲每個構造函數調用其超類構造函數,所以超類FXML將在子類FXML之前加載。

項目佈局:

enter image description here

模板:

Template.fxml:

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.scene.layout.BorderPane?> 
<?import javafx.scene.control.MenuBar?> 
<?import javafx.scene.control.Menu?> 
<?import javafx.scene.control.MenuItem?> 
<?import javafx.scene.layout.VBox?> 

<fx:root xmlns:fx="http://javafx.com/fxml/1" type="BorderPane"> 
    <top> 
     <MenuBar> 
      <menus> 
       <Menu text="File"> 
        <items> 
         <MenuItem text="Quit" onAction="#quit"/> 
        </items> 
       </Menu> 
      </menus> 
     </MenuBar> 
    </top> 

    <center> 
     <VBox fx:id="vboxCenter"/> 
    </center> 

</fx:root> 

組分(Template.java):

package template; 

import java.io.IOException; 

import javafx.fxml.FXML; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.VBox; 

public class Template extends BorderPane { 

    @FXML 
    private VBox vboxCenter ; 

    public Template() throws IOException { 
     FXMLLoader loader = new FXMLLoader(Template.class.getResource("Template.fxml")); 
     loader.setRoot(this); 
     loader.setController(this); 
     loader.load(); 
    } 

    protected final VBox getCenterContentHolder() { 
     return vboxCenter ; 
    } 

    @FXML 
    private void quit() { 
     vboxCenter.getScene().getWindow().hide(); 
    } 
} 

專業化:

Home.fxml:

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.scene.layout.VBox?> 
<?import javafx.scene.control.Label?> 
<?import javafx.scene.text.Font?> 

<fx:root xmlns:fx="http://javafx.com/fxml/1" type="VBox" alignment="CENTER"> 
    <Label fx:id="welcomeLabel" text="Welcome" /> 
</fx:root> 

組分(Home.java):

package home; 

import java.io.IOException; 

import javafx.fxml.FXML; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.control.Label; 
import javafx.scene.text.Font; 
import template.Template; 

public class Home extends Template { 

    @FXML 
    private Label welcomeLabel ; 

    public Home() throws IOException { 

     // not necessary to explicitly call super(), it is called by default 
     // this call loads the template defined by the superclass 
     super(); 

     FXMLLoader loader = new FXMLLoader(Home.class.getResource("Home.fxml")); 
     loader.setRoot(getCenterContentHolder()); 
     loader.setController(this); 

     loader.load(); 

     welcomeLabel.setFont(Font.font("Arial", 48)); 
    } 
} 

應用:

package application; 

import java.io.IOException; 

import home.Home; 
import javafx.application.Application; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 

public class Main extends Application { 

    @Override 
    public void start(Stage primaryStage) throws IOException { 
     Scene scene = new Scene(new Home(), 400, 400); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

enter image description here

+0

這非常有幫助。謝謝。 – user3668541