从 EDT 调用 invokeAndWait
我在上一个问题之后遇到了问题。我在代码库的其他地方也有代码 SwingUtillities.invokeAndWait
,但是当我删除它时,gui 不会刷新。如果我不删除它,我得到的错误是:
Exception in thread "AWT-EventQueue-0" java.lang.Error: Cannot call invokeAndWait from the event dispatcher thread
at java.awt.EventQueue.invokeAndWait(Unknown Source)
at javax.swing.SwingUtilities.invokeAndWait(Unknown Source)
at game.player.humanplayer.model.HumanPlayer.act(HumanPlayer.java:69)
HumanPlayer.act 中的代码是:
public Action act(final Action[] availiableActions) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
gui.update(availiableActions);
}
});
}
catch (InterruptedException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
synchronized(performedAction){
while(!hasPerformedAction()){
try {
performedAction.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
setPerformedAction(false);
}
return getActionPerfomed();
}
调试时线程的图像,因为屏幕不绘制: 替代文本 http://img684.imageshack.us/img684/6669/69288941.png
堆栈的文本版本:
ui.startup.LoginScreen at localhost:51050
-> Deamon Thread [AWT-Windows] (Running)
-> Thread [AWT-Shutdown] (Running)
-> Thread [AWT-EventQueue-0] (Running)
-> Thread [DestroyJavaVM] (Running)
I have a problem following from my previous problem. I also have the code SwingUtillities.invokeAndWait
somewhere else in the code base, but when I remove this the gui does not refresh. If I dont remove it the error I get is:
Exception in thread "AWT-EventQueue-0" java.lang.Error: Cannot call invokeAndWait from the event dispatcher thread
at java.awt.EventQueue.invokeAndWait(Unknown Source)
at javax.swing.SwingUtilities.invokeAndWait(Unknown Source)
at game.player.humanplayer.model.HumanPlayer.act(HumanPlayer.java:69)
The code in HumanPlayer.act is:
public Action act(final Action[] availiableActions) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
gui.update(availiableActions);
}
});
}
catch (InterruptedException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
synchronized(performedAction){
while(!hasPerformedAction()){
try {
performedAction.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
setPerformedAction(false);
}
return getActionPerfomed();
}
Image of threads when in debug as screen doesn't paint:
alt text http://img684.imageshack.us/img684/6669/69288941.png
Text version of stack:
ui.startup.LoginScreen at localhost:51050
-> Deamon Thread [AWT-Windows] (Running)
-> Thread [AWT-Shutdown] (Running)
-> Thread [AWT-EventQueue-0] (Running)
-> Thread [DestroyJavaVM] (Running)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
答案是不要从 EDT 进行调用
,而是让它在新的(非 EDT)线程上执行,以便稍后调用
invokeAndWait
时,它的功能与运行该命令的线程一样正确,而不是美东时间。修改后的代码如下:The answer was instead of making the call
from the EDT, make it execute on a new (non EDT) thread so that later when
invokeAndWait
is called it functions as correctly as the thread running that command is not the EDT. The amended code is as follows:invokeAndWait()
旨在从非 GUI 线程调用。它将一个 Runnable 对象发送到将在其中执行的 GUI 线程。将 Runnable 对象从 GUI 线程发送到自身是没有意义的。它与直接在
Runnable
对象上调用run()
的效果相同。invokeAndWait()
is meant to be called from the non-GUI thread. It sends aRunnable
object to the GUI thread where it will be executed.There's no point in sending a
Runnable
object from the GUI-thread to itself. It has the same effect as callingrun()
on theRunnable
object directly.您可以先检查当前的调用线程是否已经是事件调度程序:
请注意,
SwingUtilities.invokeAndWait(Runnable)
只是委托给EventQueue
。You can check before if your current calling thread is already the event dispatcher:
Note that
SwingUtilities.invokeAndWait(Runnable)
simply delegates to theEventQueue
.根据评论,一旦操作完成,您似乎不会重新绘制框架。如果不这样做,那么屏幕只会在看似随机的时间更新(也许当另一个窗口移动到前面时)。
在
gui.update
中,我建议您添加最后一行:(或多或少,取决于您的情况)。
编辑:事实证明,实际问题是这个循环:
由于只有一个应用程序线程(恰好是 EDT),因此
hasPerformedAction()
的结果永远不会改变(假设它是一个简单的吸气剂)。没有其他线程可以更改该值。由于这个无限循环发生在 EDT 上,因此 GUI 永远无法重新绘制;因此它锁定了。Based on the comments, it appears you are not repainting the frame once the actions are completed. If you do not, then the screen will only be updated at what seems to be random times (when another window moves in front, perhaps).
Inside
gui.update
, I suggest you make the last line:(more or less, depending on your circumstances).
Edit: As it turns out, the actual problem is this loop:
Since there is only one application thread (which happens to be the EDT), the result of
hasPerformedAction()
can never change (assuming it's a simple getter). There is no other thread to change the value. Since this infinite loop is on the EDT, the GUI can never be repainted; hence it locks up.使用 XChart java 库时,您可以使用以下代码在单击按钮时显示图表:
When using XChart java library you can show your chart on button click with this code:
尝试从此执行您的代码
try to execute your code from this