2

我是杰森。我对 Substance 的外观和感觉( https://substance.dev.java.net/ )有点问题。

我的问题更普遍。我已经写好了我的 GUI,它工作得很好,但是当我使用 Substance Look-and-feel 时,它需要在 EDT 线程(事件调度线程或其他东西)中进行所有 GUI 初始化。

现在我正在使用 com.sun.java.swing.plaf.windows.WindowsLookAndFeel (不确定我是否拼写正确),它不需要任何这类东西。

所以我通过调用 SwingUtilities.invokeLater() 将主要初始化放入 EDT。这使它工作。但是,该程序在执行过程中还会生成其他几个窗口。现在我有这样的代码:

SomeNewWindow window = new SomeNewWindow();
// ... some bs emitted
window.doStuff();

这段代码运行良好,因为在调用 window.doStuff() 时,它已经被初始化了。但是 Substance 要求我做这样的事情:

SwingUtilities.invokeLater(new Runnable(){
public void run(){
SomeNewWindow window = new SomeNewWindow();
}});
// ... bs emitted
window.doStuff();

在这里它有时会抛出 NullPointerException,因为 window 没有在 window.doStuff() 被调用时初始化。我不能将 window.doStuff() 放入 EDT 线程,因为它通常需要几秒钟才能返回并且会挂起 GUI。

我已经尝试在调用 EDT 线程后立即放置 Thread.sleep(1000),因为那时它可能已经初始化。但这似乎很尴尬。我只需要一种方法让主线程“知道” SomeNewWindow 初始化何时返回,这样它就可以继续运行而不必担心 NullPointerException。

提前致谢。

4

4 回答 4

5

您可以从invokeLater 切换到invokeAndWait,它会一直等到创建窗口。这有点俗气,但没有睡觉那么糟糕。

于 2009-02-21T22:47:37.763 回答
0

我认为解决这个问题的标准方法是让你的 EDT 成为你启动其他工作线程来做事情的“基础线程”。

另一种方法是使用volatile初始化程序在完成时可以设置的标志,以便其他线程可以在循环中检查它并在设置标志后对新窗口进行操作。

于 2009-02-21T22:23:22.533 回答
0

Egwor 建议改用CountDownLatch。绝对看起来它会简化情况。


这是条件变量的工作。

基本上,在 run() 中,锁定锁,构造一些新窗口并发出条件信号(并解锁锁)。“同时”,在另一个线程中,做你的另一个“bs”,锁定锁;如果窗口为空,则在条件变量上等待();解锁锁;窗口.doStuff();

于 2009-02-21T22:30:57.600 回答
0

是否有理由不能将 doStuff() 调用移动到 invokeLater 回调中?

SwingUtilities.invokeLater(new Runnable(){
    public void run(){
         SomeNewWindow window = new SomeNewWindow();
         window.doStuff();
    }
});

如果上述方法是不可能的,我会选择invokeAndWait()而不是invokeLater(),正如 Paul Tomblin 已经建议的那样。

于 2009-02-22T19:40:24.850 回答