这一节,我们讨论javaFX FXML 给我们带来的好处,FXML是基础xml的标记语言,我们可以使用FXML创建用户界面,这样我们可以把界面从代码中分离出来。如果你从第一篇开始看的话,你已经知道如何来创建一个登陆应用,这里我们使用FXML创建一个相同的登陆用户界面,把用户界面的应用逻辑分离这一节所建立的用户界面如下所示:
创建FXMLExample.java
创建FXMLExampleController.java
创建FXMLDocument.fxml
上面建立的文件都放在相同的包下。
package com.chu.helloworld; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; public class FXMLExample extends Application{ @Override public void start(Stage stage) throws Exception { Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml")); Scene scene = new Scene(root, 300, 275); stage.setTitle("FXML Welcome"); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
修改FXMLDocument.fxml,这个文件定义了我们的界面,首先我们需要修改导入语句,如下:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
导入的类,我们就可以使用相对应的标签。
删除AnchorPane 布局,用GridPane来替代,如下:
<GridPane fx:controller="com.chu.helloworld.FXMLExampleController"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
<padding><Insets top="25" right="25" bottom="10" left="25"/></padding>
</GridPane>
在这个应用中,GridPane布局是FXML的根元素,有两个主要的属性:
fx:controller:用来指定元素触发的事件,是事件控制类。
xmlns:fx:指定命名空间,这是必须得属性
剩下的属性指定了gridpane的排列布局信息,包括行列间距,居中。
padding元素指定了gridpane的边缘空隙
因为窗口的大小是可变的,grid面板里的节点应该跟着他们的布局约束来改变。
在这个例子里。当窗口大小改变的时候grid面板会保持在中间。padding属性可以确保党窗口更小的时候grid面板周围依然存在空隙。我们设置场景的大小为300,275。如果不设置这个大小,场景的大小默认是能容纳它的内容的最小尺寸。
在GridPane中添加如下代码:
<Text text="Welcome" GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.columnSpan="2"/> <Label text="User Name:" GridPane.columnIndex="0" GridPane.rowIndex="1"/> <TextField GridPane.columnIndex="1" GridPane.rowIndex="1"/> <Label text="Password:" GridPane.columnIndex="0" GridPane.rowIndex="2"/> <PasswordField fx:id="passwordField" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
第一行创建了一个Text对象,并且内容为 Welcome,GridPane.columnIndex 和 GridPane.rowIndex属性修正了Text控件在Grid中的位置,
grid中的行列从0开始,这个Text的位置为0,0.也就意味着放到了第一列,第一行的位置。GridPane.columnSpan属性设置的值为2,意思是这个Text对象合并了两列。下面继续创建了Label、TextField、PasswordFiled。如果想看到排列布局的详细信息我们可以加上<gridLinesVisible>true</gridLinesVisible>,运行项目如下所示:
继续在gridpane中添加如下代码:
<HBox spacing="10" alignment="bottom_right" GridPane.columnIndex="1" GridPane.rowIndex="4"> <Button text="Sign In" onAction="#handleSubmitButtonAction"/> </HBox> <Text fx:id="actiontarget" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.halignment="RIGHT" GridPane.rowIndex="6"/>
HBox需要设置按钮的对齐方式,这里的设置和gridpane布局的设置方式不同,对齐方式的值是bottom_right.意思是垂直居下,水平居右。然后这个HBox被放到布局的第一列,第四行。
HBox拥有一个子元素Button,内容为 Sign In。并且增加了onAction事件#handleSubmitButtonAction,这个事件会调用gridPane的事件控制类中指定的方法。
然后创建一个Text对象,为这个对象指定了fx:id的属性,这会创建一个变量,并且你可以在代码中的任何位置使用这个变量
增加处理事件的代码,如下:
package com.chu.helloworld; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.text.Text; public class FXMLExampleController { @FXML private Text actiontarget; @FXML protected void handleSubmitButtonAction(ActionEvent event) { actiontarget.setText("Sign in button pressed"); } }
@FXML用于非公共的控制类成员和事件处理方法。当按钮按下的时候handleSubmtButtonAction 方法把actiontarget 变量的值设为Sign in button pressed,运行应用,如下图所示:
1:我们需要删除布局上的事件控制类,也就是fx:controller
2:需要在文档开头加上<?language javascript?>
3:修改按钮的onAction属性为:onAction="handleSubmitButtonAction(event);"
4:添加脚本代码:
<fx:script>
function handleSubmitButtonAction() {
actiontarget.setText("Calling the JavaScript");
}
</fx:script>
我们也可以把脚本放到一个js文件中比如:fxml_example.js然后在文档中引用:<fx:script source="fxml_example.js"/>
运行项目可以看到,可以达到和事件控制类相同的效果
1:创建的login.css,代码如下:
.root { -fx-background-image: url("background.jpg"); } .label { -fx-font-size: 12px; -fx-font-weight: bold; -fx-text-fill: #333333; -fx-effect: dropshadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 ); } #welcome-text { -fx-font-size: 32px; -fx-font-family: "Arial Black"; -fx-fill: #818181; -fx-effect: innershadow( three-pass-box , rgba(0,0,0,0.7) , 6, 0.0 , 0 , 2 ); } #actiontarget { -fx-fill: FIREBRICK; -fx-font-weight: bold; -fx-effect: dropshadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 ); } .button { -fx-text-fill: white; -fx-font-family: "Arial Narrow"; -fx-font-weight: bold; -fx-background-color: linear-gradient(#61a2b1, #2A5058); -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 5, 0.0 , 0 , 1 ); } .button:hover { -fx-background-color: linear-gradient(#2A5058, #61a2b1); }
2:为跟元素添加样式。即为GridPane元素添加属性 styleClass="root"
3:为Welcome添加样式,为welcome的Text添加id属性:id="welcome-text"
运行应用如下图所示:
<?xml version="1.0" encoding="UTF-8"?> <?language javascript?> <?import java.net.*?> <?import javafx.geometry.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <?import javafx.scene.text.*?> <!-- fx:controller="com.chu.helloworld.FXMLExampleController" --> <GridPane fx:controller="com.chu.helloworld.FXMLExampleController" xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10" styleClass="root"> <padding> <Insets top="25" right="25" bottom="10" left="25" /> </padding> <!-- <gridLinesVisible>true</gridLinesVisible> --> <Text id="welcome-text" text="Welcome" GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.columnSpan="2" /> <Label text="User Name:" GridPane.columnIndex="0" GridPane.rowIndex="1" /> <TextField GridPane.columnIndex="1" GridPane.rowIndex="1" /> <Label text="Password:" GridPane.columnIndex="0" GridPane.rowIndex="2" /> <PasswordField GridPane.columnIndex="1" GridPane.rowIndex="2" /> <HBox spacing="10" alignment="bottom_right" GridPane.columnIndex="1" GridPane.rowIndex="4"> <Button text="Sign In" onAction="#handleSubmitButtonAction" /> </HBox> <Text fx:id="actiontarget" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.halignment="RIGHT" GridPane.rowIndex="6" /> <fx:script> function handleSubmitButtonAction() { actiontarget.setText("Calling the JavaScript"); } </fx:script> <stylesheets> <URL value="@Login.css" /> </stylesheets> </GridPane>