JavaFX入門(mén):簡(jiǎn)單Demo-學(xué)習(xí)NetBeans開(kāi)發(fā)平臺(tái)

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)單的登錄界面:

Paste_Image.png

涉及到的控件:
文本(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有多種樣式,包括了行、列、棧等等,如BorderPaneGridPane、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文件:
在包上右擊:


Paste_Image.png
Paste_Image.png

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

Paste_Image.png

樣式表中定義的內(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)前包路徑下:

Paste_Image.png

步驟三:添加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,如圖所示:

Paste_Image.png

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


Paste_Image.png

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:


Paste_Image.png

hwxk:


Paste_Image.png

"="前面,是項(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):

Paste_Image.png
Paste_Image.png

包含了配置文件和字體庫(kù)文件。
(4)code中使用:

import javafx.scene.text.Font;

Font font = Font.font("hwcy", 32);//字體,尺寸,注意不能使用加粗,即FontWeight

Paste_Image.png

(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)用程序

Paste_Image.png
Paste_Image.png

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

Paste_Image.png

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

Paste_Image.png

代碼也稍有區(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)文件名定義的比較弱,我們要自己改一下文件名,這樣才能更清晰的展示:

Paste_Image.png

注意不要忘記修改控制器和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)行:

Paste_Image.png

大致內(nèi)容都在了,但是沒(méi)有樣式,沒(méi)有登錄按鈕點(diǎn)擊處理事件。

3、 添加處理事件:

方法一:使用Java處理

//給Button增加一個(gè)事件處理
<Button text="登錄" onAction="#handleSubmitButtonAction"/>

添加之后,會(huì)報(bào)錯(cuò):

Paste_Image.png

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

Paste_Image.png

會(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)了:

Paste_Image.png

方法二.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)用腳本:

Paste_Image.png

腳本語(yǔ)言提供與JSR 223規(guī)范兼容的引擎即可。例如JavaScript、Groovy、Jython、Clojure。

方法二.2:使用外置JS腳本處理
腳本可以放在外部,正確引用即可:

Paste_Image.png
Paste_Image.png
Paste_Image.png
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é)果:

Paste_Image.png
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é)果:
Paste_Image.png

FXML方式開(kāi)發(fā)界面完成。

JavaFX Scene Builder 2.0協(xié)助開(kāi)發(fā)

JavaFX Scene Builder 2.0下載位置
下載完成,一路安裝,開(kāi)始運(yùn)行:

Paste_Image.png

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

Paste_Image.png
Paste_Image.png

選擇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)查下資料,看看如何使用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容