繁体   English   中英

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

[英]Java: GUIs must be initialized in the EDT thread?

我是杰森。 我在Substance外观( https://substance.dev.java.net/ )上遇到了一些问题。

我的问题比较笼统。 我已经写好了GUI,并且可以正常工作,但是当我使用物质外观时,它要求所有GUI初始化都必须在EDT线程(事件调度线程等)中进行。

现在,我正在使用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。

提前致谢。

您可以从invokeLater切换到invokeAndWait,它将等待直到创建窗口。 有点俗气,但还不如入睡。

我认为解决此问题的标准方法是使EDT成为“基本线程”,从该“基本线程”开始其他工作线程进行处理。

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

例如,建议使用CountDownLatch 绝对可以简化情况。


这是条件变量的工作。

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

为什么不能将doStuff()调用移到invokeLater回调中呢?

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

如果以上操作是不可能的,那么我将使用invokeAndWait()而不是invokeLater() ,就像Paul Tomblin已经建议的那样。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM