【原文地址:http://blog.ngopal.com.np/2012/01/26/fxml-stuffs-include-and-define/】
今天我想在blog里谈一谈FXML的define和include标签,这两个标签对那些想在程序里使用FXML的人非常有用。FXML是一种XML文件,JavaFX用FXMLLoader来加载它。FXML文件在运行时被加载,并且很容易学习。前一篇blog 里是一些关于FXML的基本介绍,今天这篇blog会教你如何在FXML文件里include另一个FXML。
先来看看<fx:include>
标签,现在假设我们有两个FXML文件Main.fxml和Child.fmxl。
上图中你可以看到,Child.fxml在<fx:define>里被调用到Main.fxml中,<fx:define>被用来在FXML文件里定义变量或实例(variables or instances)。
来个实际的例子,我们写一个包含tab panel的例子,每个tab的内容都是从不同的FXML文件中读取。首先,我们定义包含TabPane的Main.fxml。
Main.fxml
<?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <?import javafx.scene.shape.*?> <?import javafx.scene.effect.*?> <?import fxmlstuff.Main?> <Main xmlns:fx="http://javafx.com/fxml" fx:controller="fxmlstuff.Main" > <fx:define> <fx:include source="Home.fxml" fx:id="homeContent" /> <fx:include source="About.fxml" fx:id="aboutContent" /> </fx:define> <center> <TabPane fx:id="tabpane" translateY="5" translateX="5" > <tabs> <Tab text="HOME" fx:id="homeTab" content="$homeContent" closable="false" /> <Tab text="ABOUT" fx:id="aboutTab" content="$aboutContent" closable="false"/> </tabs> </TabPane> </center> </Main>
你可以看到,<fx:define>引入了另外两个fmxl文件,Home和About,并且分别为他们定义了fx:id,后面我们在定义Tab的content属性时,直接引用了这两个id:$homeContent,$aboutConten。
现在来看看Main.fxml的FXController类,在Main标签的fx:controller属性中定义的:fxmlstuff.Main
package fxmlstuff; import java.net.URL; import java.util.ResourceBundle; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.layout.BorderPane; /** * @author Narayan */ public class Main extends BorderPane implements Initializable{ @FXML private Home homeContent; @FXML private About aboutContent; @Override public void initialize(URL url, ResourceBundle rb) { } }
在这个controller类里,我们只是根据fx:id定义了Home和About实例。
Home.fxml
<?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <?import fxmlstuff.Home?> <Home id="homeContent" xmlns:fx="http://javafx.com/fxml" spacing="10" translateY="40" translateX="20" fx:controller="fxmlstuff.Home" > <children> <Label text="Add New Dock of Home" /> <Button text="Add !" onAction="#handleAction" /> </children> </Home>
Home.java
package fxmlstuff; import java.net.URL; import java.util.ResourceBundle; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.layout.VBox; /** * @author Narayan */ public class Home extends VBox implements Initializable{ @FXML private void handleAction(ActionEvent event) { } @Override public void initialize(URL url, ResourceBundle rb) { } }
About.fxml
<?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <?import fxmlstuff.About?> <About id="aboutContent" xmlns:fx="http://javafx.com/fxml" spacing="10" translateY="40" translateX="20" fx:controller="fxmlstuff.About"> <children> <Label text="Add New Dock of About" /> <Button text="Add !" onAction="#handleButtonAction" /> </children> </About>
About.java
package fxmlstuff; import java.net.URL; import java.util.ResourceBundle; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.layout.VBox; /** * @author Narayan */ public class About extends VBox implements Initializable { @FXML private void handleButtonAction(ActionEvent event) { } @Override public void initialize(URL url, ResourceBundle rb) { } }
现在,你已经完成了在FXML文件中添加组件,我们创建一个FXML Executor class来运行加载刚才定义的FXML文件。
FXMLTest.java
package fxmlstuff; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; /** * * @author Narayan */ public class FXMLTest extends Application{ public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage stage) throws Exception { Parent root = FXMLLoader.load(getClass().getResource("Main.fxml")); Scene scene = new Scene(root,800,600); stage.setTitle("FXML Test"); stage.setScene(scene); stage.show(); } }
运行后的界面应该是这个样子:
这篇blog的后续篇会在接下来的星期里完成,下一篇博客会对上面的程序进行扩展,我们会在Main.fmxl中处理About.fxml和Home.fxml中的组件触发的时间。