javaFX8初探(使用FXML创建登录表单)

时间:2022-01-09 13:42:09

这一节,我们讨论javaFX FXML 给我们带来的好处,FXML是基础xml的标记语言,我们可以使用FXML创建用户界面,这样我们可以把界面从代码中分离出来。如果你从第一篇开始看的话,你已经知道如何来创建一个登陆应用,这里我们使用FXML创建一个相同的登陆用户界面,把用户界面的应用逻辑分离这一节所建立的用户界面如下所示:

javaFX8初探(使用FXML创建登录表单)

创建一个javaFX Project

创建FXMLExample.java
创建FXMLExampleController.java
创建FXMLDocument.fxml

上面建立的文件都放在相同的包下。

 

加载FXML源文件,代码如下(FXMLExample.java):

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.*?>

导入的类,我们就可以使用相对应的标签。

创建GridPane布局:

删除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>,运行项目如下所示:

javaFX8初探(使用FXML创建登录表单)

 

添加按钮和文本域

继续在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,运行应用,如下图所示:

javaFX8初探(使用FXML创建登录表单)

 

使用脚本控制事件

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"/>

运行项目可以看到,可以达到和事件控制类相同的效果

 

使用CSS改变应用的样式

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"

运行应用如下图所示:

javaFX8初探(使用FXML创建登录表单)

 

fxml文档全部内容:

<?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>