JavaFX 介绍

一提到Java的图形界面库,我们通常听到的都是Swing,或者更老一点的AWT,包括很多书上面介绍的也都是这两种。很多学校、培训班教学的也是这两种技术。但是其实这两种技术都已经过时很长时间了。Swing虽然学起来也不算很难,但是用它来写界面其实也很不好写。因为它的界面和代码没有做到分离,所以在编写的时候,代码中肯定充斥着大量坐标,修改极其不易。这方面做的比较好的就是微软的WPF,只能说谁用谁知道。

当然,虽然编写客户端图形程序是Java的弱项,但是Java并没有放弃这方面的努力。今天介绍的JavaFX就是Java在编写图形界面程序的最新技术。如果你准备使用Java编写图形界面程序,又没有历史包袱,那么强烈推荐使用JavaFX。

这是Oracle官网关于JavaFX的资源和文档

这是官方的示例程序,我们可以参考JavaFX的部分来学习如何使用。下面是其中一个分形的JavaFX程序,点击上面的数字可以进入不同的微观展示,感觉有一种看病毒微观世界的感觉,很震撼。

 
img_82e4ad90d7fc50d352658513c7977731.png
分形示例程序

如何安装

只要你安装了最新版本的JDK 8,那么就可以使用JavaFX库了。如果没有安装的话,那么赶快开始安装吧。

快速上手

第一个程序

新建一个项目,然后编写如下的类,然后编译运行,即可看到结果。关于这个程序不用做解释吧。如果有学习过Swing以及其他图形界面框架的经验的话,应该非常容易理解这段代码。当然由于JavaFX是新东西,所以我也顺便使用Java 8的新特性——lambda表达式。

  1.  
    package yitian.javafxsample;
  2.  
     
  3.  
    import javafx.application.Application;
  4.  
    import javafx.scene.Scene;
  5.  
    import javafx.scene.control.Button;
  6.  
    import javafx.scene.layout.StackPane;
  7.  
    import javafx.stage.Stage;
  8.  
     
  9.  
    public class HelloJavaFX extends Application {
  10.  
     
  11.  
    @Override
  12.  
    public void start(Stage primaryStage) throws Exception {
  13.  
    Button btn = new Button();
  14.  
    btn.setText(“你好啊,世界”);
  15.  
    btn.setOnAction(event -> {
  16.  
    System.out.println(“你好,世界!”);
  17.  
    });
  18.  
     
  19.  
    StackPane root = new StackPane();
  20.  
    root.getChildren().add(btn);
  21.  
     
  22.  
    Scene scene = new Scene(root, 300, 250);
  23.  
     
  24.  
    primaryStage.setTitle(“Hello World!”);
  25.  
    primaryStage.setScene(scene);
  26.  
    primaryStage.show();
  27.  
    }
  28.  
     
  29.  
     
  30.  
    public static void main(String[] args) {
  31.  
    launch(args);
  32.  
    }
  33.  
    }
  34.  
     

运行截图如下。

 
img_c836a8643896197cc638f1619e8cb0dd.png
运行截图

用户输入

这个程序可以用来处理用户登录的情况,代码如下,重要部分都添加了注释。代码的最后一部分使用setOnAction函数为按钮添加了点击事件,当点击按钮的时候会显示文本。

  1.  
    public class UserInput extends Application {
  2.  
    @Override
  3.  
    public void start(Stage primaryStage) throws Exception {
  4.  
    //网格布局
  5.  
    GridPane grid = new GridPane();
  6.  
    grid.setAlignment(Pos.CENTER);
  7.  
    //网格垂直间距
  8.  
    grid.setHgap(10);
  9.  
    //网格水平间距
  10.  
    grid.setVgap(10);
  11.  
    grid.setPadding(new Insets(25, 25, 25, 25));
  12.  
    //新建场景
  13.  
    Scene scene = new Scene(grid, 300, 275);
  14.  
    primaryStage.setScene(scene);
  15.  
    //添加标题
  16.  
    Text scenetitle = new Text(“Welcome”);
  17.  
    scenetitle.setFont(Font.font(“Tahoma”, FontWeight.NORMAL, 20));
  18.  
    grid.add(scenetitle, 0, 0, 2, 1);
  19.  
    //添加标签及文本框
  20.  
    Label userName = new Label(“用户名:”);
  21.  
    grid.add(userName, 0, 1);
  22.  
     
  23.  
    TextField userTextField = new TextField();
  24.  
    grid.add(userTextField, 1, 1);
  25.  
    //添加标签及密码框
  26.  
    Label pw = new Label(“密码:”);
  27.  
    grid.add(pw, 0, 2);
  28.  
     
  29.  
    PasswordField pwBox = new PasswordField();
  30.  
    grid.add(pwBox, 1, 2);
  31.  
    //添加提交按钮
  32.  
    Button btn = new Button(“登录”);
  33.  
    HBox hbBtn = new HBox(10);
  34.  
    hbBtn.setAlignment(Pos.BOTTOM_RIGHT);
  35.  
    hbBtn.getChildren().add(btn);
  36.  
    grid.add(hbBtn, 1, 4);
  37.  
    //提交文本提示
  38.  
    final Text actiontarget = new Text();
  39.  
    grid.add(actiontarget, 1, 6);
  40.  
     
  41.  
    btn.setOnAction(event -> {
  42.  
    actiontarget.setFill(Color.FIREBRICK);
  43.  
    actiontarget.setText(“已经登录”);
  44.  
    });
  45.  
     
  46.  
    primaryStage.setTitle(“JavaFX Welcome”);
  47.  
    primaryStage.show();
  48.  
    }
  49.  
     
  50.  
    public static void main(String[] args) {
  51.  
    launch(args);
  52.  
    }
  53.  
    }

程序运行截图如下。

 
img_8c9ab5a1ea523aa338505ce34c748591.png
运行截图

这个程序其实也没什么难点,就是使用了网格布局,然后将每个元素添加到网格中。关于网格布局的属性意义可以参考官方的图。

 
img_b20eeacebffdffa67d5768f3395fe2a9.png
官方示意图

用FXML设计用户界面

现代图形界面框架都支持将界面和代码分离开,而且比较常用的描述语言是XML,例如QT的QML、WPF的XAML,当然JavaFX也有类似的语言,叫做FXML。如果需要详细了解FXML,可以参考Oracle官网的文章Introduction to FXML

下面用FXML重写一下上面那个小例子,每个部分都做了注释。如果学习过其他类似描述语言的话,会发现这些其实都差不多。唯一需要注意的就是布局里面的fx:controller属性,它指定一个控制器,控制器的作用就是编写界面对应的代码。

  1.  
    <?xml version=”1.0″ encoding=”UTF-8″?>
  2.  
    <!–导入类–>
  3.  
    <?import javafx.geometry.Insets?>
  4.  
    <?import javafx.scene.control.*?>
  5.  
    <?import javafx.scene.layout.*?>
  6.  
    <?import javafx.scene.text.Font?>
  7.  
    <?import javafx.scene.text.Text?>
  8.  
    <!–设置布局–>
  9.  
    <GridPane xmlns=“http://javafx.com/javafx”
  10.  
    xmlns:fx=“http://javafx.com/fxml”
  11.  
    fx:controller=“yitian.javafxsample.Controller”
  12.  
    prefHeight=“400.0” prefWidth=“600.0”
  13.  
    alignment=“center” hgap=“10” vgap=“10”>
  14.  
    <padding>
  15.  
    <Insets top=“25” right=“25” bottom=“10” left=“25”/>
  16.  
    </padding>
  17.  
    <!–欢迎文本–>
  18.  
    <Text text=“Welcome”
  19.  
    GridPane.columnIndex=“0” GridPane.rowIndex=“0”
  20.  
    GridPane.columnSpan=“2”>
  21.  
    <font>
  22.  
    <Font name=“Consolas” size=“20”/>
  23.  
    </font>
  24.  
    </Text>
  25.  
     
  26.  
    <Label text=“用户名:”
  27.  
    GridPane.columnIndex=“0” GridPane.rowIndex=“1”/>
  28.  
     
  29.  
    <TextField
  30.  
    GridPane.columnIndex=“1” GridPane.rowIndex=“1”/>
  31.  
     
  32.  
    <Label text=“密码:”
  33.  
    GridPane.columnIndex=“0” GridPane.rowIndex=“2”/>
  34.  
     
  35.  
    <PasswordField fx:id=“passwordField”
  36.  
    GridPane.columnIndex=“1” GridPane.rowIndex=“2”/>
  37.  
    <!–按钮及提示文本–>
  38.  
    <HBox spacing=“10” alignment=“bottom_right”
  39.  
    GridPane.columnIndex=“1” GridPane.rowIndex=“4”>
  40.  
    <Button text=“显示密码”
  41.  
    onAction=“#showPasswordButton”/>
  42.  
    </HBox>
  43.  
     
  44.  
    <Text fx:id=“hintText”
  45.  
    GridPane.columnIndex=“0” GridPane.columnSpan=“2”
  46.  
    GridPane.halignment=“RIGHT” GridPane.rowIndex=“6”/>
  47.  
    </GridPane>
  48.  
     

下面就是这个FXML文件对应的控制器,它是一个标准的Java类。在FXML中用fx:id属性指定的ID,可以在控制器中声明为一个类字段,通过这个字段就可以和界面组件进行交互。同样道理,onAction声明的事件处理程序,在控制器中就是一个方法。注意这些字段和方法都需要使用@FXML注解进行标注。

  1.  
    import javafx.event.ActionEvent;
  2.  
    import javafx.fxml.FXML;
  3.  
    import javafx.scene.control.PasswordField;
  4.  
    import javafx.scene.text.Text;
  5.  
     
  6.  
     
  7.  
    public class Controller {
  8.  
    @FXML
  9.  
    private Text hintText;
  10.  
    @FXML
  11.  
    private PasswordField passwordField;
  12.  
     
  13.  
    @FXML
  14.  
    protected void showPasswordButton(ActionEvent event) {
  15.  
    hintText.setText(“显示密码:” + passwordField.getText());
  16.  
    }
  17.  
    }

最后要做修改的就是主程序了。在主程序中需要使用FXMLLoader来加载FXML资源,其他部分没有太大变化。

  1.  
    public class UseFxml extends Application {
  2.  
    @Override
  3.  
    public void start(Stage primaryStage) throws Exception {
  4.  
    Parent root = FXMLLoader.load(getClass().getResource(“ui.fxml”));
  5.  
     
  6.  
    Scene scene = new Scene(root, 300, 275);
  7.  
    primaryStage.setTitle(“使用FXML”);
  8.  
    primaryStage.setScene(scene);
  9.  
    primaryStage.show();
  10.  
    }
  11.  
     
  12.  
    public static void main(String[] args) {
  13.  
    launch(args);
  14.  
    }
  15.  
    }

程序运行截图如下。

 
img_6b8f95e1364acd15cf5d2a28ea494cc6.png
运行截图

如果希望修改组件样式,JavaFX提供了CSS接口,让我们可以直接使用CSS文件修改样式。首先需要在FXML文件中添加相应样式表的引用。文件名前面的@表示这个CSS文件和FXML文件在同一目录下。

  1.  
    <GridPane>
  2.  
    <stylesheets>
  3.  
    <URL value=“@style.css”/>
  4.  
    </stylesheets>
  5.  
    <GridPane/>

样式表和普通的样式表差不多,只不过需要添加JavaFX特有的前缀-fx-

  1.  
    #btnShowPassword {
  2.  
    -fx-background-color: deeppink;
  3.  
    }

上面用了ID选择器,所以对应地,在FXML中也需要ID属性。

  1.  
    <Button id=“btnShowPassword” text=“显示密码”
  2.  
    onAction=“#showPasswordButton”/>

自定义之后的程序如图所示。这里只简单修改了一下按钮的背景色,其实可以更改的样式有很多,包括程序背景等等,有兴趣的同学可以自行尝试。

 
img_2d4aaea085a47da0302552c0df36fdd5.png
程序截图

以上就是这篇文章的内容了。如果有同学想使用Java编写图形界面程序,可以考虑使用JavaFX,这是一个很不错的选择。