JavaFX 简单学习教程 (一)

教程所有代码都是运行在 IDEA

SDK 版本 15.0.1

该版本 SDK 在 IDEA 中使用会出现小问题,但搜索引擎很容易搜到解决办法

所谓教程仅仅是自己的学习笔记

1. 最简窗口代码

显示一个窗口

package com.tenire.fxhello;

import javafx.application.Application;
import javafx.stage.Stage;

/**
 * @Description:
 * @Author: Tenire
 * @Date: 2021/8/30 23:38
 * @Email: [email protected]
 */
public class Hello extends Application
{
    public static void main(String[] args)
    {
        launch(args);
    }

    @Override
    public void start(Stage stage)
    {
        stage.show();
    }
}

如图所示,显示了一个空白窗口

窗口
窗口

2. 代码解释

代码很简单,也不难理解

但我还是打算稍微讲讲 Application 这个类

我们可以看到,在主函数里我们调用了方法 launch(args)

我们看一下官方 API 文档

Modifier and TypeMethodDescription
static voidlaunch(Class<? extends Application> appClass, String ... args)Launch a standalone application.
static voidlaunch(String ... args)Launch a standalone application.

一共两个,且都是静态方法

但有一个方法多传入了一个参数 即 继承了 Application 的类,比如上面例子中的Hello.class

那么问题来了,另外一个方法是不是就可以随便调用了?

当然不是

另外一个只能在继承了 Application 的类中调用,显然是为了简化第一种方法的参数

但是呢,第一种方法也是有很大用处的

比如继承了 Application 的类想要和主函数分离

代码如下

//Hello.java 文件
package com.tenire.fxhello;

import javafx.application.Application;

/**
 * @Description:
 * @Author: Tenire
 * @Date: 2021/8/31 0:31
 * @Email: [email protected]
 */
public class Hello
{
    public static void main(String[] args)
    {
        Application.launch(Launch.class, args);
    }


}
//Launch.java 文件
package com.tenire.fxhello;

import javafx.application.Application;
import javafx.stage.Stage;

/**
 * @Description:
 * @Author: Tenire
 * @Date: 2021/8/31 0:46
 * @Email: [email protected]
 */
public class Launch extends Application
{

    @Override
    public void start(Stage stage) throws Exception
    {
        stage.show();
    }
}

以上和之前代码效果一致,一般如果没有需求显然直接 launch 会更省事

继承了 Application 后,会要求实现方法 start(),该方法会在 launch 后自动调用

但是这不够严谨,Application 其实还有 init() stop() 方法

有过编程经验的就知道,这是 Application 的生命周期

实际上确实如此,并且他们运行顺序应该是这样:

init() start() stop()

另外,三个函数还有运行线程的区别

package com.tenire.fxhello;

import javafx.application.Application;
import javafx.stage.Stage;

/**
 * @Description:
 * @Author: Tenire
 * @Date: 2021/8/31 0:48
 * @Email: [email protected]
 */
public class Hello extends Application
{

    public static void main(String[] args)
    {
        System.out.println("main: " + Thread.currentThread().getName());
        launch(args);
    }
    @Override
    public void init() throws Exception
    {
        super.init();
        System.out.println("init: " + Thread.currentThread().getName());
    }
    @Override
    public void start(Stage stage) throws Exception
    {
        System.out.println("start: " + Thread.currentThread().getName());
        stage.show();
    }

    @Override
    public void stop() throws Exception
    {
        super.stop();
        System.out.println("stop: " + Thread.currentThread().getName());

    }
}

运行结果如下

main: main
init: JavaFX-Launcher
start: JavaFX Application Thread
stop: JavaFX Application Thread

JavaFX Application Thread 就是 UI 线程

不建议在 UI 线程之外进行 UI 操作 (似乎会报错,未测试)

一般来说,我们都是在 start() 函数中完成 UI 相关操作的

stop() 在关闭窗口后调用

start中传入了一个初始化好了的Stage

可以像以上代码那样直接调用,也可以自己 new 一个调用

3. 认识 Stage

Stage 是舞台的意思,在 JavaFX 中可以认为它是一个窗口

它实现了窗口,这个窗口包括各个平台的窗口,不同平台风格不完全一样

也就是说,Stage 可以 new 多个,show 一个就会显示一个窗口

根据程序需要进行创建即可

Stage 有很多可以调用的函数,就不一一介绍了

直接贴代码

package com.tenire.fxhello;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;

/**
 * @Description:
 * @Author: Tenire
 * @Date: 2021/9/5 14:46
 * @Email: [email protected]
 */
public class Hello extends Application
{
    public static void main(String[] args)
    {
        launch(args);
    }
    @Override
    public void start(Stage stage) throws Exception
    {
        stage.setTitle("JavaFX");   //设置标题
        

        stage.setHeight(800);   //设置高度

        stage.setWidth(1000);   //设置宽度

        stage.setMinWidth(600); //设置窗口最小宽度

        stage.setMinHeight(400);    //设置窗口最小高度

        stage.setMaxWidth(1200);    //设置窗口最大宽度

        stage.setMaxHeight(1000);   //设置窗口最大高度

        stage.getWidth();   //获取宽度

        stage.getHeight();  //获取高度
        
        
        stage.getIcons().add(new Image("icon.png"));    //设置图标
        
        
        stage.setIconified(true);   //设置窗口最小化
        
        stage.setMaximized(true);   //设置窗口最大化
        
        stage.setResizable(false);  //设置窗口是否可调大小
        
        
        stage.setOpacity(0.5);  //设置窗口不透明度
        
        
        stage.setAlwaysOnTop(true); //设置窗口始终在最上层
        
        
        stage.setX(200);    //设置窗口位置 X
        
        stage.setY(200);    //设置窗口位置 Y
        
        
        stage.setFullScreen(true);  //设置窗口全屏 设置了 Scene 才有效果
        
        stage.setScene(new Scene(new Group())); //设置 Scene 这里仅仅是最简效果
        
        
        stage.initStyle(StageStyle.DECORATED);  //设置窗口样式 默认是StageStyle.DECORATED
        
//        stage.initOwner(stage); //设置窗口归属 (另一个窗口)
        
//        stage.initModality(Modality.WINDOW_MODAL);  //窗口模态化设置
        
        //设置宽度变化监听器
        stage.widthProperty().addListener(new ChangeListener<Number>()
        {
            @Override
            public void changed(ObservableValue<? extends Number> observableValue, Number number, Number t1)
            {
                number.intValue();  //变化前宽度 可以获取其他类型数据 如 number.doubleValue();
                t1.intValue();  //变化后宽度
            }
        });
        
        //设置高度变化监听器
        stage.heightProperty().addListener(new ChangeListener<Number>()
        {
            @Override
            public void changed(ObservableValue<? extends Number> observableValue, Number number, Number t1)
            {
                number.intValue();  //变化前高度 可以获取其他类型数据 如 number.doubleValue();
                t1.intValue();  //变化后高度
            }
        });
        
        //设置位置变化监听器 X
        stage.xProperty().addListener(new ChangeListener<Number>()
        {
            @Override
            public void changed(ObservableValue<? extends Number> observableValue, Number number, Number t1)
            {
                number.intValue();  //变化前位置 X 可以获取其他类型数据 如 number.doubleValue();
                t1.intValue();  //变化后位置 X
            }
        });
        
        //设置位置变化监听器 Y
        stage.yProperty().addListener(new ChangeListener<Number>()
        {
            @Override
            public void changed(ObservableValue<? extends Number> observableValue, Number number, Number t1)
            {
                number.intValue();  //变化前位置 Y 可以获取其他类型数据 如 number.doubleValue();
                t1.intValue();  //变化后位置 Y
            }
        });
        stage.show();   //显示窗口
        stage.close();  //关闭窗口
    }
}

另附窗口样式 (默认样式为第一个)

Enum ConstantDescription
DECORATEDDefines a normal Stage style with a solid white background and platform decorations.
TRANSPARENTDefines a Stage style with a transparent background and no decorations.
UNDECORATEDDefines a Stage style with a solid white background and no decorations.
UNIFIEDDefines a Stage style with platform decorations and eliminates the border between client area and decorations.
UTILITYDefines a Stage style with a solid white background and minimal platform decorations used for a utility window.

窗口模态化参数

Enum ConstantDescription
APPLICATION_MODALDefines a Stage style with a solid white background and minimal platform decorations used for a utility window.
NONEDefines a top-level window that is not modal and does not block any other window.
WINDOW_MODALDefines a top-level window that is not modal and does not block any other window.

以上就是 Stage 有关的常用内容了

关于窗口模态化还请搜索引擎搜索

至于 Scene 之后再提了

未完待续