JavaFX入門(mén)參考,高優(yōu)質(zhì)資料:http://www.javafxchina.net/blog/docs/tutorial1/
版權(quán)所有,轉(zhuǎn)載注明。
零、 最終目標(biāo)
通過(guò)兩種方式(純代碼控制、FXML),實(shí)現(xiàn)一個(gè)簡(jiǎn)單的登錄界面:

涉及到的控件:
文本(Text,動(dòng)態(tài)顯示內(nèi)容)、標(biāo)簽(Label,顯示文本)、文本域(TextField,用戶(hù)交互輸入)、按鈕(Button,登錄點(diǎn)擊)
一、 控件通過(guò)Code動(dòng)態(tài)添加實(shí)現(xiàn)方法
1、 新建項(xiàng)目
新建JavaFXLoginDemo項(xiàng)目,具體新建方法參見(jiàn)前篇:
JavaFX開(kāi)發(fā)環(huán)境:NetBeans開(kāi)發(fā)環(huán)境搭建
完成項(xiàng)目新建后,進(jìn)入開(kāi)發(fā)正題。
入口參數(shù):
public class JavaFXLoginDemo extends Application {
@Override
public void start(Stage primaryStage) {
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
2、 布局方式
JavaFX的UI控件均擺放在Scene上,一般通過(guò)增加控制布局的Panel,并將實(shí)際的UI擺放在布局Panel上,有點(diǎn)類(lèi)似于A(yíng)ndroid的布局方式。Panel有多種樣式,包括了行、列、棧等等,如BorderPane、GridPane、Hbox、VBox等等。
本文將使用GridPane進(jìn)行布局。
GridPane grid = new GridPane();//網(wǎng)格式布局,由行列網(wǎng)格控制
grid.setAlignment(Pos.CENTER);//對(duì)齊方式,默認(rèn)靠左對(duì)齊,當(dāng)前設(shè)置居中對(duì)齊
grid.setHgap(10);//設(shè)置水平間隔
grid.setVgap(10);//設(shè)置垂直間隔
grid.setPadding(new Insets(25, 25, 25, 25));//設(shè)置Padding,順序是:上、右、下、左
Scene scene = new Scene(grid, 300, 275);//新建Scene,并將網(wǎng)格式Panel置于其中
primaryStage.setScene(scene);//設(shè)置場(chǎng)景
primaryStage.show();
3、 添加控件
Text scenetitle = new Text("歡迎標(biāo)題");
//scenetitle.setFont(Font.font("Times New Roman", FontWeight.NORMAL, 20));
grid.add(scenetitle, 0, 0, 2, 1);
//創(chuàng)建Label對(duì)象,放到第0列,第1行
Label userName = new Label("用戶(hù)名:");
grid.add(userName, 0, 1);
//創(chuàng)建文本輸入框,放到第1列,第1行
TextField userTextField = new TextField();
grid.add(userTextField, 1, 1);
Label pw = new Label("密 碼:");
grid.add(pw, 0, 2);
PasswordField pwBox = new PasswordField();
grid.add(pwBox, 1, 2);
Button btn = new Button("登錄");
HBox hbBtn = new HBox(10);
hbBtn.setAlignment(Pos.BOTTOM_RIGHT);
hbBtn.getChildren().add(btn);//將按鈕控件作為子節(jié)點(diǎn)
grid.add(hbBtn, 1, 4);//將HBox pane放到grid中的第1列,第4行
final Text actiontarget = new Text();//增加用于顯示信息的文本
grid.add(actiontarget, 1, 6);
4、 添加處理事件
只有一個(gè)按鈕需要事件處理:
btn.setOnAction(new EventHandler<ActionEvent>() {//注冊(cè)事件handler
@Override
public void handle(ActionEvent e) {
actiontarget.setFill(Color.FIREBRICK);//將文字顏色變成 firebrick red
actiontarget.setText("登錄中...");
}
});
5、 添加樣式CSS
步驟一:新建CSS文件:
在包上右擊:


輸入文件名Login.css,完成樣式表文件的創(chuàng)建:

樣式表中定義的內(nèi)容,主要用在控件的樣式控制上,需要在UI中應(yīng)用。樣式表需要應(yīng)用到Root容器中:
scene.getStylesheets().add(JavaFXLoginDemo.class.getResource("Login.css").toExternalForm());
設(shè)置后,將會(huì)在JavaFXLoginDemo.class相對(duì)路徑下尋找給出的樣式表Login.css,并應(yīng)用到scene中。
步驟二:添加一張背景圖,到當(dāng)前包路徑下:

步驟三:添加CSS樣式控制
//根元素樣式布局,設(shè)置背景圖
.root {
-fx-background-image: url("background.jpg");
}
//標(biāo)簽控件樣式
.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 );
}
//給Button增加樣式
.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);
}
//增加文本效果
#welcome-text {
-fx-font-size: 32px;
-fx-fill: #818181;
-fx-effect: innershadow( three-pass-box , rgba(0,0,0,0.7) , 6, 0.0 , 0 , 2 );
}
//登錄點(diǎn)擊事件顯示效果
#actiontarget {
-fx-fill: FIREBRICK;
-fx-font-weight: bold;
-fx-effect: dropshadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 );
}
注意,最后兩個(gè)是采用了CSS中的ID控制樣式,而非Label、Button中針對(duì)類(lèi)型設(shè)置的樣式,因此需要給目標(biāo)控件增加ID規(guī)則:
scenetitle.setId("welcome-text");
actiontarget.setId("actiontarget");
☆☆☆ 中文字體庫(kù)應(yīng)用
任何事情,涉及到了中文之后,字體庫(kù)使用有點(diǎn)麻煩。
(1)新建文件夾,在當(dāng)前包下建立resources/fonts,如圖所示:

將字體庫(kù)粘貼進(jìn)去,一般是ttf文件,Windows常用,Mac可以用,Linux也是兼容的。我粘貼的是微軟雅黑和粗體版,在Windows操作系統(tǒng)的系統(tǒng)盤(pán)下Windows/Fonts目錄下。
(2)增加fonts.mf文件
使用“文件”選項(xiàng)卡查看工程:

fonts.mf內(nèi)容:
msyh=/javafxlogindemo/resources/fonts/msyh.ttf
msyhbd=/javafxlogindemo/resources/fonts/msyhbd.ttf
hwxk=/javafxlogindemo/resources/fonts/STXINGKA.TTF
hwcy=/javafxlogindemo/resources/fonts/STCAIYUN.TTF
hwcy:

hwxk:

"="前面,是項(xiàng)目使用時(shí)的字體名稱(chēng),即font-family,后面是字體庫(kù)文件的路徑。
(3)fonts.mf需要在打包時(shí)放到j(luò)ar包的META-INF目錄下,因此需要配置NetBeans工程的build.xml文件內(nèi)容:
NetBeans工程使用Ant管理項(xiàng)目,配置的build.xml文件,根文件在工程根目錄下,具體配置文件在nbproject目錄下的build-impl.xml文件中。
在build.xml中增加如下內(nèi)容:
<target name="-post-compile">
<mkdir dir="${build.classes.dir}/META-INF"/>
<copy todir="${build.classes.dir}/META-INF" file="fonts.mf"/>
</target>
完成之后,運(yùn)行一下項(xiàng)目,在項(xiàng)目目錄的dist目錄下,可以看到打包的jar包,用壓縮文件查看器打開(kāi)(WinRAR):


包含了配置文件和字體庫(kù)文件。
(4)code中使用:
import javafx.scene.text.Font;
Font font = Font.font("hwcy", 32);//字體,尺寸,注意不能使用加粗,即FontWeight

(5)在CSS樣式文件中使用:
//增加文本效果
#welcome-text {
-fx-font-size: 32px;
-fx-font-family: "hwcy";
-fx-fill: #818181;
-fx-effect: innershadow( three-pass-box , rgba(0,0,0,0.7) , 6, 0.0 , 0 , 2 );
}
注意,-fx-font-weight: bold;加粗不能一起使用,會(huì)使字體失效。
經(jīng)過(guò)上述的配置,中文字體也能夠輕松走起啦。
6、 完成編碼,啟動(dòng)項(xiàng)目,運(yùn)行測(cè)試。
二、 FXML實(shí)現(xiàn)界面
NetBeans實(shí)現(xiàn)方法
1、 新建工程JavaFXLoginFXMLDemo:
與前一種方法新的工程種類(lèi)稍有區(qū)別,這里選擇JavaFX FXML應(yīng)用程序


對(duì)比一下工程結(jié)構(gòu),F(xiàn)XML工程多了一些FXML文件和控制器文件:

新建工程后,立刻運(yùn)行:

代碼也稍有區(qū)別,F(xiàn)XML文件中定義了控件和控制器映射關(guān)系等等:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxloginfxmldemo.FXMLDocumentController">
<children>
<Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
</children>
</AnchorPane>
默認(rèn)生成的FXML樣例界面文件中,根容器是一個(gè)AnchorPane:
AnchorPane布局面板可錨定節(jié)點(diǎn)于面板的頂、底、左邊、右邊或中間。當(dāng)窗口尺寸調(diào)整時(shí),相應(yīng)節(jié)點(diǎn)維護(hù)它們相對(duì)于錨點(diǎn)的位置。節(jié)點(diǎn)可被錨定于多個(gè)位置,多個(gè)節(jié)點(diǎn)也可錨定于同一個(gè)位置。
在后面,將要修改實(shí)際的布局容器。
控制器Controller定義了事件處理方法:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package javafxloginfxmldemo;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
/**
*
* @author guorui.he
*/
public class FXMLDocumentController implements Initializable {
@FXML
private Label label;
@FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
}
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
主文件內(nèi),與之前的純代碼實(shí)現(xiàn)基本類(lèi)似,但是加載頁(yè)面的機(jī)制稍有不同,這時(shí)通過(guò)FXML文件加載,搞過(guò)Android的人很熟悉:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package javafxloginfxmldemo;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* @author guorui.he
*/
public class JavaFXLoginFXMLDemo extends Application {
@Override
public void start(Stage stage) throws Exception {
//通過(guò)fxml的UI布局文件加載實(shí)際的界面內(nèi)容
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
由于默認(rèn)文件名定義的比較弱,我們要自己改一下文件名,這樣才能更清晰的展示:

注意不要忘記修改控制器和FXML的映射,以及主類(lèi)加載的FXML界面名稱(chēng)。
2、在FXML文件中,編寫(xiě)界面內(nèi)容:
<?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.*?>
//編寫(xiě)界面
<GridPane xmlns:fx="http://javafx.com/fxml"
fx:controller="javafxloginfxmldemo.FXMLLoginDemoDocumentController"
alignment="center" hgap="10" vgap="10">
<padding>
<Insets top="25" right="25" bottom="10" left="25"/>
</padding>
<Text text="歡迎登錄FXML Demo系統(tǒng)"
GridPane.columnIndex="0" GridPane.rowIndex="0"
GridPane.columnSpan="2"/>
<Label text="用戶(hù)名:"
GridPane.columnIndex="0" GridPane.rowIndex="1"/>
<TextField
GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<Label text="密 碼:"
GridPane.columnIndex="0" GridPane.rowIndex="2"/>
<PasswordField fx:id="passwordField"
GridPane.columnIndex="1" GridPane.rowIndex="2"/>
<HBox spacing="10" alignment="bottom_right"
GridPane.columnIndex="1" GridPane.rowIndex="4">
<Button text="登錄" />
</HBox>
<Text fx:id="actiontarget"
GridPane.columnIndex="0" GridPane.columnSpan="2"
GridPane.halignment="RIGHT" GridPane.rowIndex="6"/>
</GridPane>
此時(shí),沒(méi)有添加事件處理,可以試運(yùn)行:

大致內(nèi)容都在了,但是沒(méi)有樣式,沒(méi)有登錄按鈕點(diǎn)擊處理事件。
3、 添加處理事件:
方法一:使用Java處理
//給Button增加一個(gè)事件處理
<Button text="登錄" onAction="#handleSubmitButtonAction"/>
添加之后,會(huì)報(bào)錯(cuò):

需要在控制器中為其添加事件處理:

會(huì)自動(dòng)的在控制器內(nèi)添加處理程序:
package javafxloginfxmldemo;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.text.Text;
/**
*
* @author guorui.he
*/
public class FXMLLoginDemoDocumentController implements Initializable {
private Label label;
@FXML
private PasswordField passwordField;
@FXML
private Text actiontarget;
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
@FXML
private void handleSubmitButtonAction(ActionEvent event) {
actiontarget.setText("登錄中...");
}
}
@FXML注解,可以刪除,最好保留,閱讀方便。
添加好處理事件后,點(diǎn)擊登錄按鈕,就會(huì)有反應(yīng)了:

方法二.1:使用內(nèi)置JS腳本處理
<?xml version="1.0" encoding="UTF-8"?>
<?language javascript?>
添加腳本聲明。
修改Button的事件處理方法(局部代碼):
<GridPane xmlns:fx="http://javafx.com/fxml"
fx:controller="javafxloginfxmldemo.FXMLLoginDemoDocumentController"
alignment="center" hgap="10" vgap="10">
<!-- 腳本處理代碼 -->
<fx:script>
function handleSubmitButtonAction() {
actiontarget.setText("Calling the JavaScript");
}
</fx:script>
<HBox spacing="10" alignment="bottom_right"
GridPane.columnIndex="1" GridPane.rowIndex="4">
<Button text="登錄" onAction="handleSubmitButtonAction(event);"/>
</HBox>
<Text fx:id="actiontarget"
GridPane.columnIndex="0" GridPane.columnSpan="2"
GridPane.halignment="RIGHT" GridPane.rowIndex="6"/>
</GridPane>
點(diǎn)擊之后,調(diào)用腳本:

腳本語(yǔ)言提供與JSR 223規(guī)范兼容的引擎即可。例如JavaScript、Groovy、Jython、Clojure。
方法二.2:使用外置JS腳本處理
腳本可以放在外部,正確引用即可:



function handleSubmitButtonAction() {
actiontarget.setText("Calling the Outline JavaScript");
}
同時(shí),在FXML中引入腳本:
<GridPane xmlns:fx="http://javafx.com/fxml"
fx:controller="javafxloginfxmldemo.FXMLLoginDemoDocumentController"
alignment="center" hgap="10" vgap="10">
<fx:script source="FXMLJSLoginDemo.js"/>
<HBox spacing="10" alignment="bottom_right"
GridPane.columnIndex="1" GridPane.rowIndex="4">
<Button text="登錄" onAction="handleSubmitButtonAction(event);"/>
</HBox>
<Text fx:id="actiontarget"
GridPane.columnIndex="0" GridPane.columnSpan="2"
GridPane.halignment="RIGHT" GridPane.rowIndex="6"/>
</GridPane>
試運(yùn)行,得到結(jié)果:

4、 添加樣式控制:
添加樣式表文件、字體庫(kù)文件、背景圖片,增加fonts.mf配置文件,修改build.xml等等,與前面純代碼開(kāi)發(fā)基本一致,注意路徑名(包名有變化)。
在FXML中引入樣式表,并給特定的控件增加id,以便于CSS樣式篩選器能夠正確篩選適配:
<GridPane xmlns:fx="http://javafx.com/fxml"
fx:controller="javafxloginfxmldemo.FXMLLoginDemoDocumentController"
alignment="center" hgap="10" vgap="10"
styleClass="root" >
<stylesheets>
<URL value="@Login.css" />
</stylesheets>
<Text id="welcome-text" text="歡迎登錄FXML Demo系統(tǒng)"
GridPane.columnIndex="0" GridPane.rowIndex="0"
GridPane.columnSpan="2"/>
<Text id="actiontarget" fx:id="actiontarget"
GridPane.columnIndex="0" GridPane.columnSpan="2"
GridPane.halignment="RIGHT" GridPane.rowIndex="6"/>
</GridPane>
5、 最終運(yùn)行結(jié)果:

FXML方式開(kāi)發(fā)界面完成。
JavaFX Scene Builder 2.0協(xié)助開(kāi)發(fā)
JavaFX Scene Builder 2.0下載位置
下載完成,一路安裝,開(kāi)始運(yùn)行:

非常簡(jiǎn)單的一個(gè)界面,就是做做界面……
配置一下:


選擇JavaFX Scene Builder安裝主目錄,即可。
然后,雙擊或者右擊打開(kāi)FXML,則會(huì)自動(dòng)使用SB編輯器打開(kāi)。
尾
NetBeans是JavaFX的一個(gè)開(kāi)發(fā)工具,比較好用。
除此之外,e(fx)clipse也是一個(gè)不錯(cuò)的JavaFX開(kāi)發(fā)工具,有時(shí)間可以適當(dāng)查下資料,看看如何使用。