零、 最終目標
通過兩種方式(純代碼控制、FXML),實現一個簡單的登錄界面:

涉及到的控件:
文本(Text,動態顯示內容)、標簽(Label,顯示文本)、文本域(TextField,用戶交互輸入)、按鈕(Button,登錄點擊)
一、 控件通過Code動態添加實現方法
1、 新建項目
新建JavaFXLoginDemo項目,具體新建方法參見前篇:
JavaFX開發環境:NetBeans開發環境搭建
完成項目新建后,進入開發正題。
入口參數:
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上,一般通過增加控制布局的Panel,並將實際的UI擺放在布局Panel上,有點類似於Android的布局方式。Panel有多種樣式,包括了行、列、棧等等,如BorderPane、GridPane、Hbox、VBox等等。
本文將使用GridPane進行布局。
GridPane grid = new GridPane();//網格式布局,由行列網格控制 grid.setAlignment(Pos.CENTER);//對齊方式,默認靠左對齊,當前設置居中對齊 grid.setHgap(10);//設置水平間隔 grid.setVgap(10);//設置垂直間隔 grid.setPadding(new Insets(25, 25, 25, 25));//設置Padding,順序是:上、右、下、左 Scene scene = new Scene(grid, 300, 275);//新建Scene,並將網格式Panel置於其中 primaryStage.setScene(scene);//設置場景 primaryStage.show();
3、 添加控件
Text scenetitle = new Text("歡迎標題"); //scenetitle.setFont(Font.font("Times New Roman", FontWeight.NORMAL, 20)); grid.add(scenetitle, 0, 0, 2, 1); //創建Label對象,放到第0列,第1行 Label userName = new Label("用戶名:"); grid.add(userName, 0, 1); //創建文本輸入框,放到第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);//將按鈕控件作為子節點 grid.add(hbBtn, 1, 4);//將HBox pane放到grid中的第1列,第4行 final Text actiontarget = new Text();//增加用於顯示信息的文本 grid.add(actiontarget, 1, 6);
4、 添加處理事件
只有一個按鈕需要事件處理:
btn.setOnAction(new EventHandler<ActionEvent>() {//注冊事件handler @Override public void handle(ActionEvent e) { actiontarget.setFill(Color.FIREBRICK);//將文字顏色變成 firebrick red actiontarget.setText("登錄中..."); } });
5、 添加樣式CSS
步驟一:新建CSS文件:
在包上右擊:


輸入文件名Login.css,完成樣式表文件的創建:

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

步驟三:添加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 ); } //給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 ); } //登錄點擊事件顯示效果 #actiontarget { -fx-fill: FIREBRICK; -fx-font-weight: bold; -fx-effect: dropshadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 ); }
注意,最后兩個是采用了CSS中的ID控制樣式,而非Label、Button中針對類型設置的樣式,因此需要給目標控件增加ID規則:
scenetitle.setId("welcome-text"); actiontarget.setId("actiontarget");
☆☆☆ 中文字體庫應用
任何事情,涉及到了中文之后,字體庫使用有點麻煩。
(1)新建文件夾,在當前包下建立resources/fonts,如圖所示:

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

fonts.mf內容:
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:

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


包含了配置文件和字體庫文件。
(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;
加粗不能一起使用,會使字體失效。
經過上述的配置,中文字體也能夠輕松走起啦。
6、 完成編碼,啟動項目,運行測試。
二、 FXML實現界面
NetBeans實現方法
1、 新建工程JavaFXLoginFXMLDemo:
與前一種方法新的工程種類稍有區別,這里選擇JavaFX FXML應用程序


對比一下工程結構,FXML工程多了一些FXML文件和控制器文件:

新建工程后,立刻運行:

代碼也稍有區別,FXML文件中定義了控件和控制器映射關系等等:
<?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>
默認生成的FXML樣例界面文件中,根容器是一個AnchorPane:
AnchorPane布局面板可錨定節點於面板的頂、底、左邊、右邊或中間。當窗口尺寸調整時,相應節點維護它們相對於錨點的位置。節點可被錨定於多個位置,多個節點也可錨定於同一個位置。
在后面,將要修改實際的布局容器。
控制器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 } }
主文件內,與之前的純代碼實現基本類似,但是加載頁面的機制稍有不同,這時通過FXML文件加載,搞過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 { //通過fxml的UI布局文件加載實際的界面內容 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); } }
由於默認文件名定義的比較弱,我們要自己改一下文件名,這樣才能更清晰的展示:

注意不要忘記修改控制器和FXML的映射,以及主類加載的FXML界面名稱。
2、在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 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系統" GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.columnSpan="2"/> <Label text="用戶名:" 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>
此時,沒有添加事件處理,可以試運行:

大致內容都在了,但是沒有樣式,沒有登錄按鈕點擊處理事件。
3、 添加處理事件:
方法一:使用Java處理
//給Button增加一個事件處理 <Button text="登錄" onAction="#handleSubmitButtonAction"/>
添加之后,會報錯:

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

會自動的在控制器內添加處理程序:
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注解,可以刪除,最好保留,閱讀方便。
添加好處理事件后,點擊登錄按鈕,就會有反應了:

方法二.1:使用內置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>
點擊之后,調用腳本:

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



function handleSubmitButtonAction() { actiontarget.setText("Calling the Outline JavaScript"); }
同時,在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>
試運行,得到結果:

4、 添加樣式控制:
添加樣式表文件、字體庫文件、背景圖片,增加fonts.mf配置文件,修改build.xml等等,與前面純代碼開發基本一致,注意路徑名(包名有變化)。
在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系統" 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、 最終運行結果:

FXML方式開發界面完成。
JavaFX Scene Builder 2.0協助開發
JavaFX Scene Builder 2.0下載位置
下載完成,一路安裝,開始運行:

非常簡單的一個界面,就是做做界面……
配置一下:


選擇JavaFX Scene Builder安裝主目錄,即可。
然后,雙擊或者右擊打開FXML,則會自動使用SB編輯器打開。
尾
NetBeans是JavaFX的一個開發工具,比較好用。
除此之外,e(fx)clipse也是一個不錯的JavaFX開發工具,有時間可以適當查下資料,看看如何使用。
作者:heguorui
鏈接:https://www.jianshu.com/p/a80d1eedc507
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。