上一篇文章介绍了maven创建javafx项目的一些注意的地方,并且展示了两种不同的项目结构和运行演示。本文先自己写一个简单的实例,并介绍生命周期。

创建一个普通的maven项目,然后在pom.xml中引入下面配置,然后在resource目录中放一个ico.jpg文件作为窗口的图标。

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>13</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <release>11</release>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>0.0.4</version>
                <configuration>
                    <mainClass>xin.jiangqiang.App</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

创建下面java代码,然后运行即可。

public class Test1 extends Application {

    @Override
    public void start(Stage stage) throws Exception {
//        var label = new Label("Hello, JavaFX");
//        var scene = new Scene(new StackPane(label), 640, 480);
//        stage.setScene(scene);
//        stage.show();

        stage.setTitle("HelloWorld");
//        stage.getIcons().add(new Image("file:ico/ico.jpg"));
        stage.getIcons().add(new Image("/ico.jpg"));

//        stage.setIconified(true);//设置最小化
//        stage.setMaximized(true);//设置最大化
        stage.setWidth(500);
        stage.setHeight(500);
//        stage.setResizable(false);//不可以拖动窗口调整窗口大小
//        stage.setMaxHeight(800);//可以拖动调整的最大高度
        //获取高度,如果没有设置宽和高,那么这个方法只能在设置显示之后才能获取宽和高。
        System.out.println(stage.getHeight());
//        stage.setFullScreen(true);//设置全屏
        stage.setScene(new Scene(new Group()));
        stage.heightProperty().addListener(new ChangeListener<Number>() {
            /**&
             *
             * @param observable 包括了改变后的状态信息
             * @param oldValue 改变尺寸前的值
             * @param newValue 改变后的值
             */
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                System.out.println("之前的高度" + oldValue + "当前的高度" + newValue);
//                System.out.println(observable);//封装了改变之后的数据信息
                System.out.println(Thread.currentThread().getName());
            }
        });
        stage.show();
        stage.widthProperty().addListener(new ChangeListener<Number>() {
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                System.out.println("之前的宽度" + oldValue + "当前的宽度" + newValue);
                System.out.println(Thread.currentThread().getName());

            }
        });
//        stage.close();//关闭
    }

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

运行之后可以看见一个空白的窗口。
image.png

注意:这个窗口你可以理解为stage,而去掉顶部最小化,最大化和关闭按钮之外的部分,就是Scene。我们之后的文章中主要是对scene进行操作。

我们再通过一段代码来简单了解一下stage:

public class TestStage extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        stage.setTitle("HelloWorld");
        stage.getIcons().add(new Image("ico/ico.jpg"));
        stage.show();
        Stage stage1 = new Stage();
        stage1.show();
        Stage stage2 = new Stage();
        stage2.show();
        Stage stage3 = new Stage();
        stage3.initModality(Modality.APPLICATION_MODAL);//禁止点击同一个应用的其他窗口
        stage3.show();
//        Platform.exit();//关闭所有窗口
    }

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

stage就是包含最大化最小化和关闭按钮的窗口,我们可以同时创建多个stage并显示。在start方法中默认就传入了一个stage对象。其实我们也可以自己创建stage对象,我们可以看源码发现,start方法参数传入的stage对象也是new构造器的方式创建的。

在最上面的实例中,我使用了事件监听,写法和swing的事件监听是类似的,这个不需要死记硬背,常用的事件主要就是鼠标键盘相关的,需要用到则百度,可以自行测试我注释掉的代码。此处事件监听的作用就是窗口大小改变时触发,我们拖动边框修改窗口大小,可以看见控制台会输出当前大小。阅读到这里,我们还要记住一个javafx项目的代码结构:

  1. 首先需要继承Application类
  2. 实现start方法
  3. main方法中调用launch方法即可。

最后我们来测试一下生命周期:

public class TestLife extends Application {
    public static void main(String[] args) {
        System.out.println("main() = " + Thread.currentThread().getName());
        System.out.println("launch() = " + Thread.currentThread().getName());
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        System.out.println("start() = " + Thread.currentThread().getName());
        primaryStage.show();
    }

    @Override
    public void init() throws Exception {
        System.out.println("init()开始执行");
        Thread.sleep(5000);
        super.init();
        System.out.println("init() = " + Thread.currentThread().getName());
    }

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

运行结果:

main() = main
launch() = main
init()开始执行
init() = JavaFX-Launcher
start() = JavaFX Application Thread
stop() = JavaFX Application Thread

我们可以发现首先是main线程执行main方法,然后执行launch方法。之后会创建一个JavaFX-Launcher线程开始执行应用程序的init方法。该方法执行完毕之后才会创建JavaFX Application Thread线程执行start方法。当我们关闭程序时,会执行stop方法。
init方法不在JavaFX应用程序线程上调用。应用程序不能用这个方法里构造Scene或Stage。应用程序可以在此方法中构造其他JavaFX对象。
start方法创建并显示UI。
stop方法用于销毁资源。

Q.E.D.


擅长前端的Java程序员