JavaFX 学习记录

Posted on 2023-02-28 09:21  Choimoe  阅读(28)  评论(0编辑  收藏  举报

使用 JavaFX 时一些奇怪的问题

继承自 Application 类的构造函数会被执行两次

先看代码:

// FXTestMain.java
import javafx.application.Application;
import javafx.stage.Stage;

public class FXTestMain extends Application {
    public void main(String[] args) { launch(args); }
    int counter = 0;
    public FXTestMain() {
        System.out.println(++counter);
    }
    @Override
    public void start(Stage stage) {}
}


//FXtest.java
public class FXTest {
    public static void main(String[] args) {
        FXTestMain GUI = new FXTestMain();
        GUI.main(args);
    }
}

将会输出:

1
1

在 Line.9 打个断点,会发现这一句会被线程 mainJavaFX Application Thread 都执行一遍,然而把 GUI.main(args) 注释掉后就很正常。于是考虑看 launch 到底干了什么:(经过反编译后的代码)

// Application.class: Line.52
LauncherImpl.launchApplication(var12, var0);

// LauncherImpl.class: Line.82
launchApplication(var0, var2, var1);

// LauncherImpl.class: Line.98
launchApplication1(var0, var1, var2);

// LauncherImpl.class: Line.514-522
try {
    Constructor var3 = var1.getConstructor();
    var10.set((Preloader)var3.newInstance());
    ParametersImpl.registerParameters((Application)var10.get(), new ParametersImpl(var2));
} catch (Throwable var4) {
    System.err.println("Exception in Preloader constructor");
    pConstructorError = var4;
    error = true;
}

可见 launch 方法中通过 ConstructornewInstance() 创建和初始化一个新实例,会调用它的构造方法。

使用 SourceDataLine 播放音频错误重复循环一片段

The sound of putting chess pieces suddenly gets out of control. · Issue #2 · Choimoe/GoChess (github.com)

个人猜测是因为多次播放,对 buffer 的抢占导致的。在 Doc4dev 文档 里可以看到具有非实时声音数据且可以预加载到内存时,应该使用使用Clip,尤其是它已经被加载进内存的情况下。

解决办法:使用 Clip 进行播放。但是也会导致相邻两子间隔太短而吞音,不整了。

Main 方法结束后,程序仍未退出

我创建了 IOThread 类,在读取存档时候会被调用,而常态在 wait 状态:

    public void reStartRead() {
        try {
            synchronized (this) {
                this.notify();
                additionAction();
                this.wait();
            }
        } catch (InterruptedException e) {
            System.out.println("[ERROR] Cannot restart thread to start read saves.");
            e.printStackTrace();
        }
    }

只要在退出时使用 this.interrupt(); 就好了(不要使用已经废弃的 stop())。