JavaFX2.0基础教程 之 FXML入门教程

时间:2021-07-23 14:11:27

 

1        FXML入门教程

本部分教程包括两部分内容:

  1、为什么使用FXML(基本介绍以及用FXML创建用户界面的好处);

  2、使用FXML创建用户界面(通过创建简单登录应用来完成本教程部分)。

1.1 为何使用FXML

FXML是基于XML的语言,它提供与应用逻辑代码分离的构建用户界面的结构。展现层和应用逻辑的分离对web开发者更有吸引力:因为他们可以利用java组件组装用户界面而不需要掌握获取并填充数据的代码。

接下的部分提供更多关于FXML的信息,之后你会选择FXML创建用户界面而不是其它方法。下面分三部分介绍FXML

l  FXML介绍;

l  FXML简单示例;

l  FXML好处。

1.1.1   FXML介绍

FXML没有相应的模式,但有一个基本的预定义结构。用FXML表达什么,如何用它构建场景图,依赖于你构造对象的API。因为FXML直接映射到Java,参照API文档以更好地什么理解元素和属性允许应用。通常,大多数JavaFX类能作为元素使用,大多数Bean的Properties特性可以用作属性。

来源于模型-视图-控制器(MVC)观点,FXML文件包含用户界面描述的部分称之为视图。控制器是可选性实现Initializable类的Java类,这被声明为FXML文件的控制器。模型由定义java端的域对象构成,并通过控制器连接到视图。在“使用FXML创建用户界面”中有一个结构性示例。

使用FXML创建用户界面时,对大而复杂的布景、表单、数据实体或是复杂动画,使用FXML是特别有用的。FXML也是适合定义静态布局结构,诸如表单、控件和表等。另外,通过包含脚本还能使用FXML构建动态布局。

1.1.2  FXML简单示例

最简单展示FXML好处的方法是实例。如图1-1所示,它展示了一个包含Pane布局的用户界面,Pane布局有一个顶部和中部区域,每个区域中包含一个label标签。

JavaFX2.0基础教程 之 FXML入门教程

图1-1 边格简单示例

说明:布局类BorderPane定义两个区域:顶部区域和中部区域。顶部区域包含一个“Page Title”标签,中部区域包含一个“some data here”标签。

首先,看下用户界面结构如何,在源代码中如何直接创建,如下示例1-1所示。

BorderPaneborder = new BorderPane();

Labeltoppanetext = new Label("Page Title");

border.setTop(toppanetext);

Label centerpanetext= new Label ("Some data here");

border.setCenter(centerpanetext);

示例1-1 用户界面的java代码

     现在看下示例1-2,展示相同的用户界面,但是用FXML标记的。这儿能看到用户界面的层次结构,这更容易依次添加控件构建用户界面。

<BorderPane>

    <top>

        <Label text="PageTitle"/>

    </top>

    <center>

        <Label text="Some datahere"/>

    </center>

</BorderPane>

示例1-2 FXML标记用户界面

1.1.3   FXML的好处

除了提供给web开发者一个熟悉的用户界面设计方法万,FXML还提供如下好处:

Ø  由于场景图在FXML中更透明,这使开发团队更容易创建和维护一个可测试的用户界面;

Ø  FXML是非编译语言,无需重编译就可查看变化;

Ø  FXML文件内容可以本地化处理。例如,如果一个FXML文件使用en_US本地化加载,它基于下面资源字符串产生 “First Name” 字符串标签:<Label text="%firstName"/>。如果本地化变为fr_FR,这个FXML文件重新加载,这标签将展示“Prénom”。相同的事情对java代码则不行。因为你需要获得相应引用后,必须手动更新每个用户界面元素内容,并正确调用setter

Ø  可以和任何JVM语言一起使用FXML,诸如JavaScale或者Clojure

Ø  FXML不局限与MVC模型的视图部分。你可以构造服务、任务或域对象,并且你可以在FXML中使用javascript或其它脚本语言。关于使用脚本示例,请参考本教程“使用脚本语言”部分。

1.2 创建用户界面

通过前述介绍,现在已经对怎么使用FXML有了一定认知,接下来将在教程实战中更好理解。这个实战介绍怎么创建如图2-1所示的登录界面。

JavaFX2.0基础教程 之 FXML入门教程

图2-1登录界面

图例说明:应用标题为“LoginExample”。标签重叠了一个背景图片。从顶到底,应用程序中的控件是:带文本“Sign In”的标签、带“UserName”的文本框、带“Password”的密码框以及一个提交按钮。

开始前,熟悉下登录界面布局,如图2-2所示。用户界面使用了一个包含两个区域的边格布局(Border Pane)。顶部区域包含一个堆栈布局,内有文字“Label Example”并层叠在一个图片上。中间区域包含一个网格布局,并含有标签、文本框、密码框以及按钮。

JavaFX2.0基础教程 之 FXML入门教程

图2-2登陆界面布局

 

1.2.1   准备工作

本部分教程使用到NetBeansIDE。确定你在使用的NetBeans IDE版本支持JavaFX2.0。更多相关细节参考“系统要求”部分。

为了完成这个教程,应该熟悉如何用JavaFX程序性构建用户界面。了解如何与布景图一起工作时特别有益处的。因为FXML的层次结构和JavaFX布景图结构是密切相关的。

1.2.2   创建工程

首先在NetBeans的IDE中创建一个JavaFX工程。

1.        从“文件”(File)菜单,选择“新工程”(New Project);

2.        在JavaFX应用分类中选择JavaFX FXML 应用。点击下一步;

3.        命名工程为FXMLExample并点击“完成”(Finish)。IDE打开带有3个文件的工程:FXMLExample.java,Sample.fxml以及Sample.java;

4.        下载一个淡蓝渐变的背景图片,并保持到桌面,然后拖动到在源代码包目录下的fxmlexample目录。

1.2.3   创建应用基础

每个FXML应用必须包括java代码。最少包括创建stage和scene以及加载launch应用的代码。

打开FXMLExample.java,删除IDE生成的代码,并用示例2-1代码替换。

packagefxmlexample;

 

importjava.util.ResourceBundle;

importjavafx.application.Application;

importjavafx.fxml.FXMLLoader;

importjavafx.scene.Parent;

importjavafx.scene.Scene;

importjavafx.stage.Stage;

 

public classFXMLExample extends Application {

    @Override

    public void start(Stage stage) throwsException {

        stage.setTitle("FXMLExample");

       

        Parent root =FXMLLoader.load(getClass().getResource("fxml_example.fxml"),

           ResourceBundle.getBundle("fxmlexample.fxml_example"));       

        Scene scene = new Scene(root, 226,264);

        stage.setScene(scene);

        stage.show();

    }

 

    public static void main(String[] args) {

        launch(args);

    }

}

示例2-1FXMLExampel.java

作为JavaFX程序员,创建布景和舞台以及加载应用的代码应该是熟悉的。下面这行指向于相应的FXML文件:

Parent root =FXMLLoader.load(getClass().getResource("fxml_example.fxml"),ResourceBundle.getBundle("fxmlexample.fxml_example"));

这个FXMLLoader.load()方法从资源文件fxml_example.fxml中加载层级对象,并赋值到名为root的变量。getRsources()实现资源绑定,以便于具体化界面中的字符串,也更容易资源本地化处理。接下来的两部分,将回到资源绑定部分——属性文件和创建FXML源文件。

总体来说,创立布景对象,并设置root变量未场景图的根。FXML中这个根元素将作为布景图的根节点。

1.2.4   创建属性文件

一个最佳实践是具体化用户界面的文本字符串到一个属性文件。可采取如下步骤创建登录界面的属性文件。

1.             在工程窗口,右键点击fxmlexample文件夹,并选择“新建”(new),然后点击“其它”(Other);

2.             在新文件对话框中点击“其它”(Other),选择Properties文件,点击“下一步”(next);

3.             键入fxml_example作为文件名,点击“完成”(Finish)。然后IDE打开以.properties为扩展名的文件;

4.             键入资源名称和值,如下示例2-2所示:

loginExample=LoginExample

signIn=Sign in:

userName=Username:

password=Password:

submit=Submit

 

1.2.5   创建FXML文件

现在创建一个名称为fxml_example.fxml的FXML文件,并插入xml声明,导入语句。

1.      在项目窗口,在fxmlexample文件夹下右键点击Sample.fxml,选择“重命名”(Rename);

2.      键入fxml_example,点击“OK”;

3.      打开fxml_example文件,删除IDE生成的代码,并以示例2-3的的代码替换。

<?xmlversion="1.0" encoding="UTF-8"?>

 

<?importjavafx.scene.layout.*?>

<?import javafx.scene.control.*?>

<?importjavafx.scene.*?>

<?importjavafx.scene.image.*?>

示例2-3声明和导入语句

所有FXML文件必须以XML声明开始。它定义了XML的版本(1.0)和编码类型(UTF-8)。与在JavaFX里一样,类名必须合乎规范(包括包名),或者也可以使用导入语句导入,如示例2-3所示。如果你喜欢,也可使用具体导入语句指向你的类。

 

1.2.6   定义边格布局

接下来开始构建用户界面。再导入语句之后插入边格布局内容,如示例2-4所示:

<BorderPanefx:controller="fxmlexample.FXMLExampleController"

   xmlns:fx="http://javafx.com/fxml">

     <top>

     </top>

     <center>

     </center>

</BorderPane>

示例2-4 边格布局


在这个示例中,场景图的根是边格布局类。它定义了顶部和中部两个区域。fx:controller属性指定控制文件,且必须在根FXML元素内声明。在后续的讲学习更多关于控制器内容。

xmlns:fx=”http://javafx.com/fxml”属性把命名空间映射到URL为http://javafx.com/fxml的位置。必须在FXML根元素中声明命名空间。这个属性可以确保相应JavaFXAPI元素能通过FXML标签来使用。

 

1.2.7   图片上堆叠文本

接下来在顶部区域嵌套一个堆栈窗格。这个窗格上包含了一个叠加在图片的标签。如图2-3所示。

JavaFX2.0基础教程 之 FXML入门教程

图2-3 边格布局顶部区域,包含栈窗格

堆窗格代码如示例2-5所示。把下列代码插入到<top>和</top>标签之间。

<StackPane>

            <children>   

                <ImageView>

                   <image>

                        <Imageurl="@fx_boxback.jpg"/>

                   </image>

                </ImageView>

                <Labeltext="%loginExample" style="-fx-font: NORMAL 20Tahoma;"/>

            </children>

        </StackPane> 

StackPane布局类把它的子节点放在单一堆栈内,每新增一个节点都会防止在前一个节点之上。这种布局模式提供了一种简单的图片上叠加文字的方式。

标签<children>实现把子节点增加到布局图上,这很类似于JavaFX中使用getChildren().add()方法。

图片Image类加载“fx_boxback.jpg”,此文件假设放置在当前FXML文件位置。ImageView类把图片展示在屏幕上。

标签Label类有个文本属性设置资源名称loginExample。在FXML中,一个资源名称由%号操作符唯一指定。加载时,FXML加载器用它的值(LoginExample)替换loginExaple资源名称。

注意:FXML用style属性定义风格。在示例2-5中,Label类使用了style属性设置了字体风格。

另一种定义风格的方法是定义CSS,和在java中使用方法一样。使用CSS可以更容易在以后重定制应用风格。

 

1.2.8   添加Grid布局和控件

接下来,在边格布局的中部区域嵌入Grid布局。以水平和垂直的方式在Grid布局上放置控件。如图2-4所示。

JavaFX2.0基础教程 之 FXML入门教程

图2-4 边格布局中部的Grid面板

示例2-6包含了这个grid布设的代码。把它插入到<center>和</center>标签中间。

<GridPanealignment="top_center" hgap="8" vgap="8"

            style="-fx-padding: 40 0 00">

            <children>

                <Labeltext="%signIn"

                    style="-fx-font:NORMAL 14 Tahoma;"

                    GridPane.columnIndex="0"GridPane.rowIndex="0"/>

 

                <Labeltext="%userName"

                   GridPane.columnIndex="0" GridPane.rowIndex="1"

                   labelFor="$usernameField"/>

                <TextField fx:id="usernameField"prefColumnCount="10"

                   GridPane.columnIndex="1" GridPane.rowIndex="1"/>

 

                <Labeltext="%password"

                   GridPane.columnIndex="0" GridPane.rowIndex="2"

                   labelFor="$passwordField"/>

                <PasswordFieldfx:id="passwordField" prefColumnCount="10"

                   GridPane.columnIndex="1" GridPane.rowIndex="2"

                   onAction="#handlePasswordFieldAction"/>

 

                <Buttonfx:id="submitButton" text="%submit"

                   GridPane.columnIndex="1" GridPane.rowIndex="3"

                   onAction="#handleSubmitButtonAction"/>

 

                <Labelfx:id="buttonStatusText"

                    GridPane.columnIndex="1"GridPane.rowIndex="4"

                    style="-fx-text-fill:#ff0000;"/>

            </children>

        </GridPane>

示例2-6 带控件的Grid布设

这儿的代码现在看起来很熟悉,但也有些新属性需要解释。GridPane.columnIndex和GridPane.rowIndex属性对应GridPane类的setColumnIndex()和setRowIndex()方法。行列的数量从0开始。例如,第一个Label控件的位置是(0,0),这意味着他在第一行第一列。或是左上角。PrefColumnCount属性被用于TextField和PasswordField控件,预设置10列。

把值fx:id赋予一个文档命名空间里创建变量的元素,以便后续代码中引用。变量引用通过$操作符来标记。在示例2-6中,TextField的ID是usernameField。这个ID被赋予控件Label的labelFor属性,以便为TextField设置标签。

注意PasswordField和Button控件有个onAction属性,这个数字签名引用一个定制方法,这个方法你可以在下一节创建FXMLExampleController类时定义。

尽管FXML是定义应用用户接口结构的便捷方式,但并不提供应用行为的实现方式。这个行为必须在java代码或脚步语言中实现(下一节将描述)。

 

1.2.9   添加按钮事件

现在,创建一个控制器来处理按钮事件。这个例子演示了java写的事件处理器如何与FXML标记关联。

1.             在工程窗口,在fxmlexample文件夹下右击Sample.java,并选择“Refactor”,然后选择“Rename”(重命名);

2.             键入FXLExampelController并点击“Refactor”;

3.             打开FXMLExampleController.java文件,删除IDE生成代码,并用示例2-7代码替换之。

packagefxmlexample;

 

importjavafx.event.ActionEvent;

importjavafx.fxml.FXML;

importjavafx.scene.control.Label;

 

public class FXMLExampleController{

  @FXML private Label buttonStatusText;

   

   @FXMLprotected void handleSubmitButtonAction(ActionEvent event) {

        buttonStatusText.setText("Submitbutton pressed");

    }

 

    @FXML protected voidhandlePasswordFieldAction(ActionEvent event) {

        buttonStatusText.setText("Enterkey pressed");

    }

}

示例2-7 FXMLExampleController.java

@FXML标注用于标签非公共控制器成员字段域,并且由标签使用相应的处理器方法。另外,对于java编程语言,你也可使用其它编译语言,如Scala来实现控制器。

现在可以运行这个应用程序。在两个输入域键入文本并点击“Submit”(提交)测试下这个应用,看看如何。

完整的应用代码可以下载这个压缩包“FXMLExample.zip”。

 

1.2.10  使用脚本语言

相对于使用java常见事件处理器,你也能使用提供了JSR223兼容的脚本引擎的语言来创建处理器。诸如JavaScript、Groovy、Jython和Clojure。在登录示例中采用javascript按如下步骤编辑FXML文件。

1.      在fxml_example.fxml文件中,在XML声明后增加Javascript声明。

<?language  javascript?>

2.      在按钮标记中,改变下功能名称,调用如下所示:

onAction=”handleSubmitButtonAction(event);”

3.      更新PasswordField标记,类似如下:

onAction=”handlePasswordFieldAction(event);”

4.      从BorderPane标记中删除fx:controller属性,并在<script>标签中直接增加JavaScript功能,如示例2-8所示:

<BorderPanexmlns:fx="http://javafx.com/fxml">

         <fx:script>

             functionhandleSubmitButtonAction() {

                buttonStatusText.setText("Calling the JavaScript");

             }

             functionhandlePasswordFieldAction(event) {

                 buttonStatusText.text ="More JavaScript";

             }

         </fx:script>

示例2-8FXML中 JavaScript

另外一种选择是你可以把Javascript功能放在一个外部文件(如fxml_example.js)中,然后通过下面脚本包含近来:

<fx:script source="fxml_example.js"/>

如果你考虑和FXML一起使用脚本语言,注意,在调试期间可能IDE不支持进入相应脚本代码。

1.2.11  应用式样表

作为内嵌样式替代物,你可以对布景使用式样表,然后设置节点的样式类。按照如下步骤创建式样表,并定义了Grid面板和Label控件的样式。

1.      创建式样表

a.  在工程窗口,右击源码包目录下的fxmlexample文件夹,选择“New”然后选择“Other”;

b.  在新的文件对话框,选择Other,然后选择“CascadingStyle Sheet”,再点击“Next”;

c.  键入fxmlstylesheet,点击“Finish”;

d.  删除IDE生成代码,用示例2-9的代码替换

@charset"utf-8";

/*

    Document  : FXMLstylesheet.css

*/ 

.grid-pane {

  -fx-padding: 80 0 0 0;

}

.label {

    -fx-font: normal 36px Tahoma;

}

 

2.      打开FXMLExample.java文件在代码行stage.show()前包含如下代码增加样式表到布景中

scene.getStylesheets().add("fxmlexample/fxmlstylesheet.css");

3.      到fxml_example。Fxml文件并增加式样类。

a.      为<String>元素增加导入语句。<?import java.lang.*?>

b.      用示例2-10代码替换GridPane标签内容

<GridPanealignment="top_center" hgap="8" vgap="8">

           <styleClass>

                <Stringfx:value="grid-pane"/>

            </styleClass>

示例2-10

c.      用示例2-11代码替换“Sign In”标签

<Labeltext="%signIn"                   

    GridPane.columnIndex="0"GridPane.rowIndex="0">

         <styleClass>

               <Stringfx:value="label"/>

         </styleClass>

</Label>

在一个对象内使用<styleClass>标签时,式样被应用到所有同类实例(除了类有自己的内联式样)。因此,当你运行FXMLExample应用是,示例2-11式样被应用到不仅仅是Sign标签,也应用到了Username和Password标签。式样没有应用到登录示例的标签,因为他有一个内有式样覆盖了这个样式表。

 

 

1.2.12  教程回顾

下面简单回顾一下教程信息点:

l  FXML是JavaFX的组件。它是个创建JavaFX应用用户界面的可选项;

l  FXML是基于XML的;

l  FXML文件作为规则JavaFX工程的一部分,不需要编译;

l  FXML层次架构和JavaFX布景图结构对应;

开始FXML文件的最佳编码实践是带有XML声明: <?xml version="1.0"encoding="utf-8"?>

FXML命名空间必须定义在XML代码中组件顶层,以便FXML标签整体使用,例如:<rootElement xmlns:fx="http://javafx.com/fxml">

通过资源文件的字符串提取,FXML能本地化处理。资源替代通过%标识;

FXML定义样式和java代码中setStyle()定义CSS类似。既可以使用内联式样,也可使用样式表;

给元素fx:id赋值,以便后续引用。引用时通过$标识变量;

除了javaFXML支持其他编译语言实现的控制器,如Scala

FXML支持任何JSR223兼容的脚本引擎,这样的语言包括JavaScriptGroovyJython以及Clojure等。

1.3  接下来…

现在已熟悉了FXML,可以进一步查看FXML介绍文档,文档提供了关于FXML语言元素的更多信息。文档包含在javafx.fxml包里,详见这里

另外,也可自行扩展上面的FXML应用,比如校验用户名不能为空,增加取消按钮等。