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

发布于 2024-07-14 04:10:49 字数 1125 浏览 9 评论 0原文

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

我的问题更普遍。 我已经编写了 GUI 并且它工作正常,但是当我使用 Substance Look-and-feel 时,它要求所有 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.doStuff() 时窗口尚未初始化。 我无法将 window.doStuff() 放入 EDT 线程中,因为它通常需要几秒钟的时间才能返回,并且会挂起 GUI。

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

提前致谢。

I'm Jason. I'm having a bit of a problem with the Substance look and feel (https://substance.dev.java.net/).

My problem is more general. I've already got my GUI written and it works fine, but when I use a Substance Look-and-feel, it requires all GUI initialization to take place in the EDT thread (Event Dispatching Thread or something).

Right now I'm using com.sun.java.swing.plaf.windows.WindowsLookAndFeel (not sure if I spelled that right) and it doesn't require anything of this sort.

So I put the main initialization into the EDT by calling SwingUtilities.invokeLater(). This made it work. However, the program also spawns several other windows during its execution. Right now I have code like:

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

This code works fine because by the time window.doStuff() is called, it's already initialized. But Substance requires me to do something like this:

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

Here it sometimes throws a NullPointerException because window is not initialized by the time window.doStuff() is called. I can't put window.doStuff() into the EDT thread because it usually takes several seconds to return and will hang the GUI.

I've tried putting Thread.sleep(1000) right after I invoke the EDT thread because it's probably initialized by then. But this seems awkward. I simply need a way for the main thread to 'know' when the SomeNewWindow initialization has returned so it can continue on without having to worry about a NullPointerException.

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

赠佳期 2024-07-21 04:10:49

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

You could switch from invokeLater to invokeAndWait, which will wait until the window is created. It's a bit cheesy, but not as bad as putting in a sleep.

怪异←思 2024-07-21 04:10:49

我认为对此的标准方法是让您的 EDT 成为“基本线程”,您可以从中启动其他工作线程来执行操作。

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

I think the standard approach to this would be to make your EDT the "base thread" from which you start other worker threads to do stuff.

Another way would be to use a volatile flag that the initializer can set when it's done, so the other thread can check it in a loop and act on the new window once the flag is set.

墨落画卷 2024-07-21 04:10:49

Egwor建议使用 CountDownLatch 相反。 看起来肯定会简化情况。


这是 条件的工作变量

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

Egwor suggest using a CountDownLatch instead. Definitely looks like it would simplify the situation.


This is a job for condition variables.

Basically, in run(), Lock the lock, construct some new window and signal the condition (and unlock the lock).
"Meanwhile", in the other thread, do your other "bs", lock the lock; if the window is null, wait() on the condition variable; unlock the lock; window.doStuff();

生来就爱笑 2024-07-21 04:10:49

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

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

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

Is there a reason why you can't just move the doStuff() call into the invokeLater callback?

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

If the above is impossible, I'd go with invokeAndWait() instead of invokeLater(), as Paul Tomblin already suggested.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文