Java:必须在EDT线程中初始化GUI?

时间:2009-02-21 22:18:33

标签: java multithreading user-interface swing look-and-feel

我是杰森。我对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,因为窗口没有被时间窗口初始化。调用了doStuff()。我不能将window.doStuff()放入EDT线程,因为它通常需要几秒钟才能返回并挂起GUI。

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

提前致谢。

4 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:0)

我认为这样做的标准方法是让你的EDT成为“基础线程”,从中启动其他工作线程来做东西。

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

答案 2 :(得分:0)

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


这是condition variables的工作。

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

答案 3 :(得分:0)

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

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

如果上述情况不可能发生,我会选择invokeAndWait()代替invokeLater(),就像保罗·汤姆林已经建议的那样。