2016-12-08 156 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