转载

JavaFX 学习笔记——窗口与控件

前言

如今比较流行的桌面gui框架有WPF、WinForm、Qt、javafx等。其中WPF和WinForm目前还只能在运行Winsows上。Qt(widget)是一个很强大的跨平台C++框架(不只是UI),但用C++写界面实在有点蛋疼,且编译出来的体积很大。

JavaFX是基于JAVA的开源桌面框架,笔者曾学习过Qt,打算尝试使用Java写桌面应用,现在网上关于JavaFX的教程不时很多,因此在这里记录一下学习过程。

安装和配置

JavaFX11的环境不包括在JDK中,因此要在配置好JDK11的基础上单独配置,具体方法可以参考 JavaFX官网 。

窗口构成

新建工程,在 Main.java 中输入下列代码:

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{

        VBox layout = new VBox();
        Label label = new Label("Hello world");
        layout.getChildren().add(label);

        Scene scene = new Scene(layout, 300, 300);

        primaryStage.setTitle("Hello World");
        primaryStage.setScene(scene);
        primaryStage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }
}

JavaFX中的 Stage 可以看作是窗口, Scene 是窗口中的内容,调用 StagesetScene 函数来设置窗口内容,窗口可以在运行时切换显示的 Scene ,实现 Tab 页面的效果。

VBox 是JavaFX中的一种布局,其中的元素纵向排列,向 VBox 中添加元素需要调用 vbox.getChildren().add(control) ,如上所示。

构造 Scene 时传入顶层的布局(类似Qt中 QMainWindowCentralWidget )及大小。最后调用 show 函数将窗口显示出来。

按钮控件

控件(Control)是GUI框架中最重要的部分,也是用户与程序进行交互的媒介。

在JavaFX中使用控件需要导入包,例如

import javafx.scene.control.Label;
import javafx.scene.control.*;

框架中不同控件的使用方法大同小异,这里用最常用的按钮作为示例。

在窗口中添加按钮

构造一个 Button 对象并添加到 VBox 中:

Button button = new Button("Click me");
VBox layout = new VBox();
layout.getChildren().add(button);

Scene scene = new Scene(layout, 300, 300);
primaryStage.setScene(scene);

为按钮添加事件

使用 EventHandler 接口

创建 Handler 类实现 EventHandler 接口

class Handler implements EventHandler<ActionEvent> {

    @Override
    public void handle(ActionEvent actionEvent) {
        if(actionEvent.getSource() instanceof Button)
            ((Button) actionEvent.getSource()).setText("Click me again");
    }
}

为按钮注册点击方法

button.setOnAction(new Handler());

Button 还有 setOnMouseClicked , setOnTouchPressed 等方法,这些是专门为处理鼠标事件及触摸事件, setOnAction 函数用来处理按钮触发事件(不管按钮被哪种方式触发,具体参考 文档 )。

由代码可以得出, setOnAction 函数接收一个 EventHandler 接口,接口的 handle 方法用来处理事件。

使用匿名内部类

与上一方法同理,我们可以使用匿名内部类创建接口

button.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent actionEvent) {
        if(actionEvent.getSource() instanceof Button)
            ((Button) actionEvent.getSource()).setText("Click me again");
    }
});

使用 Lambda 表达式

Java 中的一些接口可以由 lambda 表达式代替,因此可以在 setOnAction 中传入 lambda 表达式:

button.setOnAction(actionEvent -> {
    if(actionEvent.getSource() instanceof Button){
        ((Button) actionEvent.getSource()).setText("Click me again");
    }
});

这样就可以在实现简单的事件处理器时不必再特意实现接口。

其他控件

使用其他控件的方法也都类似按钮,使用时可以查询文档,或者根据IDE的代码提示获知函数签名及使用方法。

多窗口

在一个桌面程序中往往有多个窗口,下面介绍添加窗口的方法。

创建窗口

添加 MsgBox

public class MsgBox {
    public static void show(String title) {
        Stage window = new Stage();
        window.setTitle(title);


        Button trueButton = new Button("True");
        Button falseButton = new Button("False");

        HBox hBox = new HBox(10);    //10为元素间空隙
        hBox.getChildren().addAll(trueButton, falseButton);
        Scene scene = new Scene(hBox, 100, 100);
        window.setScene(scene);
        window.show();
    }
}

与主窗口创建过程相同,新建 stageScene 、布局及控件,最后使用 Stageshow 方法显示出来。

调用 MsgBox 类的 show 方法即可显示窗口,函数的参数为窗口的标题。

设置主窗口中的按钮事件,点击按钮后会显示一个 MsgBox 窗口。

button.setOnAction(actionEvent -> MsgBox.show("SubWindow"));

返回子窗口的值

有时我们需要得到用户在子窗口中的操作,例如在本文的例子中,获知用户点了哪一个按钮。

接下来实现这样的功能——点击True按钮就在控制台打印 true ,否则打印'false'。

更改 MsgBox 中的代码

public static boolean show(String title) {
    Stage window = new Stage();
    window.setTitle(title);

    Button trueButton = new Button("True");
    Button falseButton = new Button("False");

    trueButton.setOnAction(actionEvent -> {
        answer = true;
        window.close();
    });

    falseButton.setOnAction(actionEvent -> {
        answer = false;
        window.close();
    });

    HBox hBox = new HBox(10);
    hBox.getChildren().addAll(trueButton, falseButton);
    Scene scene = new Scene(hBox, 100, 100);
    window.setScene(scene);
    window.showAndWait();

    return answer;
}

show 函数返回一个 boolean 类型的值,这个值是由点击的按钮决定的,按钮点击后会关闭窗口,返回布尔值。

设置主窗口中按钮点击事件

button.setOnAction(actionEvent ->
{
        var result = MsgBox.show("SubWindow");
        System.out.println(result);
});

showAndWait 函数

这个函数会阻塞当前事件,直到窗口被关闭后才会返回,并执行接下类的语句。在上例中,我们显示窗口并等待,直到点击按钮使窗口被关闭,才执行后面的 return answer 语句。

可以尝试改为调用 show 方法,观察返回的结果。

链接

  1. 推荐一个很好的JavaFX教程视频: https://youtu.be/FLkOX4Eez6o
  2. 一个适合初学者的Qt教程: https://www.devbean.net/2012/...
原文  https://segmentfault.com/a/1190000018109949
正文到此结束
Loading...