我的previous problem发生了问题。我在代码库中的其他地方也有代码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();
}
调试时线程的图像,因为屏幕不绘制: alt text 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)
答案 0 :(得分:7)
答案不是拨打电话
new GameInitializer(userName, player, Constants.BLIND_STRUCTURE_FILES.get(blindStructure), handState);
来自EDT的,使其在新的(非EDT)线程上执行,以便稍后在调用invokeAndWait
时它正常运行,因为运行该命令的线程不是EDT。修改后的代码如下:
Thread t = new Thread(new Runnable() {
@Override
public void run() {
new GameInitializer(userName, player, Constants.BLIND_STRUCTURE_FILES.get(blindStructure), handState);
}
});
t.start();
答案 1 :(得分:4)
invokeAndWait()
旨在从非GUI线程调用。它将Runnable
对象发送到GUI线程,然后执行它。
从GUI线程向自身发送Runnable
对象是没有意义的。它与直接在run()
对象上调用Runnable
具有相同的效果。
答案 2 :(得分:1)
根据评论,一旦操作完成,您似乎没有重新绘制框架。如果你不这样做,那么屏幕只会在似乎是随机的时间更新(当另一个窗口在前面移动时,也许)。
在gui.update
内,我建议你做最后一行:
myFrame.repaint();
(或多或少,取决于您的具体情况)。
编辑:事实证明,实际问题是这个循环:
synchronized(performedAction){
while(!hasPerformedAction()){
try {
performedAction.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
setPerformedAction(false);
}
由于只有一个应用程序线程(恰好是EDT),hasPerformedAction()
的结果永远不会改变(假设它是一个简单的getter)。没有其他线程可以更改该值。由于这个无限循环在EDT上,因此GUI永远不会被重新绘制;因此它锁定了。
答案 3 :(得分:1)
如果当前的调用线程已经是事件调度程序,您可以检查:
private void syncExec(final Runnable r) {
try {
if (EventQueue.isDispatchThread()) r.run();
else EventQueue.invokeAndWait(r);
} catch (final Exception e) {
Throws.throwRuntime(e);
}
}
请注意,SwingUtilities.invokeAndWait(Runnable)
只是委托给EventQueue
。
答案 4 :(得分:0)
使用 XChart java 库时,您可以使用以下代码在按钮单击时显示图表:
JButton btn = new JButton("View chart");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
new SwingWrapper(yourChart).displayChart();
}
});
t.start();
}
});