1

我想要一个应用程序来创建一组固定的 Swing 对象,例如在定义明确的/中央/应用程序范围的位置中的实例Font和,例如和。ColorGuiFonts.javaGuiColors.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 对象?

4

2 回答 2

1

字体和颜色是 AWT 的一部分,而不是 Swing。

话虽如此,我已经完成了您用字体概述的内容。

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 上使用此变量,就可以了。您正在 EDT 上执行方法代码。

您可以将字体代码放入方法中。

public static Font getNormalFont() {
    return new Font(Font.SANS_SERIF, Font.PLAIN, 12);
}

这样,当从 EDT 调用时,您可以确定代码正在 EDT 上执行。

于 2013-01-22T20:38:31.517 回答
1

Swing 已经为这些东西提供了一个“定义明确的/中央/应用程序范围的位置”:UIManager

使用它的好处是字体、颜色等将由 Swing 自动设置,您不必设置它们。

另请参阅:设置 Swing 程序的默认字体

编辑:如果您需要创建 Swing 组件,它们肯定必须在 EDT 上创建。请注意,一些较旧的文档说,如果它们尚未“实现”,那么在其他线程上创建组件是安全的,但这是过时的建议。

于 2013-01-22T20:51:49.930 回答