2010-11-22 86 views
4

我试了很多,但似乎无法让它工作。如何更新线程内的JFrame标签? - Java

我被告知使用EDT与下面的例子。

SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      // Modify the GUI here 
     } 
}); 

我已阅读了这个话题很多,仍然不明白。我得到了一个线程,但.invokeLater对我仍然没有任何意义。老实说,如果你可以详细解释这将是一个很大的帮助!

程序目标:获取每秒不断创建的随机生成的密钥,以便在GUI中随后进行更新。

+1

除了@John V.的回答下面,你可能想要阅读这篇文章:[Threads and Swing](http://java.sun.com/products/jfc/tsc/articles/threads/threads1 .html) – casablanca 2010-11-22 21:37:50

回答

3

所以有一个EDT(事件调度线程)。出现在屏幕上的所有操作都由EDT执行。每个秋千应用只有一个EDT。

你在一些任意线程,你想通过该线程更新QUI?就像我说的那样,每个摇摆应用程序只有一个EDT,所以你必须告诉EDT显示标签(或任何你想要的上下文)。

这里的想法是,你把这个Runnable推到一个美国东部时间从一个队列中拉出来。最终,您的可运行应用程序将在EDT执行之前执行所有其他操作。

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(); 
+0

.updateUI();不断出现一个错误,当我尝试用.setText()更改标签时;你在哪里发布//更新变量在这里,我总是最终没有帮助我。所以我认为,而不是JFrame我需要mainFrame(它扩展了我以前使用的JFrame),所以没有工作...所以基本上我不知道这是甚至假设让我更新它。我会读这本书建议“肮脏的富客户端”肯定... – Zeveso 2010-11-22 23:26:40

+0

事实证明`component.repaint()`更符合你所寻找的内容。抱歉。我已经更新了我的答案。 – 2010-11-24 20:14:20

1

我建议你买到书Filthy Rich Clients。有一章讲解了Swing的线程模型的细节。

基本上在Swing中,任何修改GUI的代码都应该在Event Dispatcher Thread中执行。您在那里使用的SwingUtilities类为您提供了一种将事件发布到事件队列的简便方法,该事件队列由EDT分派。这就是invokeLater方法所做的,它需要一个new Runnable()作为最终在EDT上执行的参数。

从书:

中,invokeLater()实现需要 负责创建和排队一个特殊的 事件包含了Runnable的。这个 事件在EDT上以 的顺序进行处理,就像任何 其他事件一样。当其到达时,通过运行 Runnable的run()方法调度 。

0

这是所有GUI编程中很常见的元素。您有一个线程可以处理绘制GUI,获取输入和运行回调。如果另一个线程试图改变与GUI相关的对象,它将与GUI线程发生冲突。举个例子,举个例子,绘制一些东西的方法是一半,然后你改变另一个线程的颜色。

所有的invokeLater都会排队等待GUI线程运行。通过“稍后”它实际上几乎立即运行,但当前线程不必等待它。 GUI线程可能正在进行绘制或等待回调,以便延迟执行您提供的代码。

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摇摆。

当您在EDT(在事件处理程序中运行代码)时,如果您确实需要,可以调用paintImmediately()。