我已经尝试了很多,但似乎无法让它发挥作用。
我被告知在下面的例子中使用EDT。
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// Modify the GUI here
}
});
我已经阅读了很多这个主题但仍然不明白。我得到的是一个线程,但.invokeLater对我来说仍然没有意义。老实说,如果你能 详细解释 ,这将是一个很大的帮助!
计划目标:获取随机生成的密钥,该密钥每秒都会不断创建,以便在GUI中自动更新。
答案 0 :(得分:4)
所以有一个EDT(Event Dispatch Thread)。屏幕上显示的所有操作均由EDT执行。每个Swing应用程序只有一个EDT。
你在某个任意线程中,你想通过该线程更新GUI?就像我说的每个swing应用程序只有一个EDT,所以你必须告诉EDT显示标签(或你想要的任何上下文)。
这里的想法是,你将这个Runnable推送到EDT拉出的队列中。最终,当完成之前的所有其他操作时,EDT将处理您的runnable。
答案 1 :(得分:2)
我建议你拿到这本书Filthy Rich Clients。有一章他们会详细解释Swing的线程模型。
基本上在Swing中,任何修改GUI的代码都应该在Event Dispatcher Thread中执行。您在那里使用的SwingUtilities
类为您提供了一种将事件发布到事件队列的简单方法,然后由EDT调度。这就是invokeLater
方法的作用,它需要new Runnable()
作为参数,最终在EDT上执行。
从书中可以看出:
invokeLater()实现需要 关心创建和排队特殊 包含Runnable的事件。这个 事件在EDT中处理 订单收到了,就像任何一样 其他事件。当它到来的时候,它 通过运行来调度 Runnable的run()方法。
答案 2 :(得分:0)
如果您要做的就是按照已知的时间表更新UI,请尝试以下操作。这假定JFrame
是您希望每1秒更新一次的组件。
private static final int WAIT_LENGTH = 1000; // 1 second
private JFrame frame = new JFrame();
// Thread will update the UI (via updateUI() call) about every 1 second
class UIUpdater extends Thread {
@Override
void run() {
while (true) {
try {
// Update variables here
}
catch (Exception e) {
System.out.println("Error: " + e);
}
finally {
frame.repaint();
Thread.sleep(WAIT_LENGTH);
}
}
}
}
开始这个帖子:
UIUpdater t = new UIUpdater();
t.start();
答案 3 :(得分:0)
这是所有GUI编程中非常常见的元素。您有一个线程可以处理绘制GUI,获取输入和运行回调。如果另一个线程试图更改GUI相关对象,它将与GUI线程冲突。比方说,例如,它是绘制内容的一半,并且您从不同的线程更改颜色。
所有invokeLater都会为GUI线程排队等待运行。通过“稍后”它几乎立即运行,但当前线程不必等待它。 GUI线程可能正在进行绘制或等待回调,这将延迟执行您提供的代码。
答案 4 :(得分:0)
需要成为会员,以便我们可以更改它并仍然使用内部类
protected long secret=0;
...这需要在您的代码中某处运行...
JFrame f = new JFrame("foo");
new Thread(){
public void run() {
for(;;){
try {
sleep(1000);
} catch Interrupted (Exception ix){
return;
}
// TODO update your secret key here
// please don't use random()
SwingUtilities.invokeLater(new Runnable() {
public void run() {
f.setTitle("secret "+x);
}
});
}
}
}).start();
...
只有从EDT更新Swing才能正确绘制。
当你在EDT(在事件处理程序中运行代码)时,你可以调用paintImmediately(),如果你真的必须。