我的应用程序的主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循环结束才触发它。
知道为什么吗?
答案 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