Swing Window Listener线程问题

时间:2015-05-07 20:28:50

标签: java swing

我的应用程序的主JFrame上有一个Window Listener。我还在应用程序中的按钮上有一个按钮监听器。我用它作为按钮监听器的模式:

good.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent ev) { 
    // We're going to do something that takes a long time, so we
    // spin off a thread and update the display when we're done.
    Thread worker = new Thread() {
      public void run() {
        // Report the result using invokeLater().
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            for(int i=0; i<1000000; i++){
               System.out.println("foo");
            }
          }
        });
      }
    };
    worker.start(); // So we don't hold up the dispatch thread.
  }
});

当我单击按钮时,我会看到每次迭代的打印输出,但是在循环执行完之后才会触发窗口监听器。打印'foo'就是为了模拟需要一段时间的东西,我希望一旦窗口事件发生就会触发监听器(这可能是在run()方法执行过程中的某个地方),但它似乎直到for循环结束才触发它。

知道为什么吗?

2 个答案:

答案 0 :(得分:3)

Swing是单线程的 - Event Dispatch Thread(EDT)管理Swing的绘画和事件。放置在EDT上的任何长时间运行的任务都将阻止EDT执行任务,直到长时间运行的任务完成(换句话说,UI看起来已被锁定)。在这里,您的代码使用for将长时间运行的进程(SwingUtilities循环)调度到EDT上 - 如果您有一个长时间运行的任务并且在此过程中想要一个响应式Swing UI,那么请长时间运行任务进入它自己的Thread,或使用SwingWorker

答案 1 :(得分:2)

所以,这一切......

goEnrichment

将会导致循环在Event Dispatching Thread的上下文中执行,这将阻止EDT处理事件队列,包括绘制请求。

在您的情况下,使用 // Report the result using invokeLater(). SwingUtilities.invokeLater(new Runnable() { public void run() { for(int i=0; i<1000000; i++){ System.out.println("foo"); } } }); 可能更容易,您可以使用SwingWorker / publish信息从后台线程到EDT,并支持进度通知< / p>

有关详细信息,请参阅How to use SwingWorker