我想要一个应用程序来创建一组固定的 Swing 对象,例如在定义明确的/中央/应用程序范围的位置中的实例Font
和,例如和。Color
GuiFonts.java
GuiColors.java
这样,我的应用程序可以引用类似的内容:GuiFonts.SMALL_FONT
和例如。GuiColors.BACKGROUND
#FFEF88
#AAAAFFF
那么,我应该如何编写这些默认值呢?特别是,我应该如何编写它们以确保它们在 Swing Event Dispatch Thread (EDT) 可见性方面被正确初始化?
我相信在 EDT 上创建和引用 Swing GUI 对象是正确的,并且只在 EDT 上 - 是吗?
那么,这样的事情就足够了吗,还是因为代码将在类加载器线程而不是 EDT 上运行而在某种程度上不够?或者只要引用在非 EDT 线程上运行就足够了static final
?
import java.awt.Font;
public class GuiFonts {
// not running on EDT, but is it correct anyhow?
public static final Font = new Font(Font.SANS_SERIF, Font.PLAIN, 16);
}
或者,我是否应该确保在 EDT 上创建对象,可能像这样:
import java.awt.*;
import java.util.concurrent.*;
import javax.swing.*;
public class GuiFonts {
// intended to run on EDT, but is EDT running yet? In all cases?
public static final Font MEDIUM_FONT = new Callable<Font>() {
@Override
public Font call() {
final RunnableFuture<Font> future = new FutureTask<Font>(new Callable<Font>() {
@Override
public Font call() {
return new Font(Font.SANS_SERIF, Font.PLAIN, 16);
}
});
try {
SwingUtilities.invokeAndWait(future); // Could be invokeLater() because of the Future...
return future.get();
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
}.call();
}
当然,这很冗长,但其中很多可以打包到一个接受 aCallable
并将其提交给 EDT 的例程中:
public static final Font MEDIUM_FONT = runOnEDT(new Callable<Font>() {
@Override
public Font call() {
return new Font(Font.SANS_SERIF, Font.PLAIN, 16);
}
});
除了 Swing EDT 发布问题之外,如果常量在多个文件中相互引用,这种方法还有一个容易出错的初始化排序方面:未使用 be 初始化的常量null
。
请注意,这样的例程runOnEDT
应该捕获并记录所有异常,特别是,日志记录应该发生在catch
子句中而 不是在某些子句中,UncaughtExceptionHandler
因为UncaughtExceptionHandler
通常已经安装在 EDT 上。
或者,最好static
一起放弃初始化。支持一些延迟加载方案,其中对象由enum
常量表示,并且某些访问器在第一次引用时在 Swing EDT 上创建 GUI 对象?