【发布时间】:2011-01-29 21:02:55
【问题描述】:
在stackoverflow 上的人们的帮助下,我能够获得以下简单 GUI 倒计时的工作代码(它只显示一个倒计时的窗口)。这段代码的主要问题是invokeLater 的东西。
据我了解invokeLater,它会向事件调度线程 (EDT) 发送一个任务,然后 EDT 在“可以”时执行此任务(无论这意味着什么)。 对吗?
据我了解,代码是这样工作的:
在
main方法中,我们使用invokeLater来显示窗口(@987654327@ 方法)。换句话说,显示窗口的代码将在 EDT 中执行。在
main方法中,我们还启动counter并且计数器(通过构造)在另一个线程中执行(因此它不在事件调度线程中)。对吧?counter在单独的线程中执行,并定期调用updateGUI。updateGUI应该更新 GUI。 GUI 在 EDT 中工作。所以,updateGUI也应该在 EDT 中执行。这就是updateGUI的代码包含在invokeLater中的原因。对吗?
我不清楚为什么我们从 EDT 调用 counter。无论如何,它不会在 EDT 中执行。它立即启动,一个新线程和counter 在那里执行。那么,为什么我们不能在 invokeLater 块之后的 main 方法中调用 counter?
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class CountdownNew {
static JLabel label;
// Method which defines the appearance of the window.
public static void showGUI() {
JFrame frame = new JFrame("Simple Countdown");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
label = new JLabel("Some Text");
frame.add(label);
frame.pack();
frame.setVisible(true);
}
// Define a new thread in which the countdown is counting down.
public static Thread counter = new Thread() {
public void run() {
for (int i=10; i>0; i=i-1) {
updateGUI(i,label);
try {Thread.sleep(1000);} catch(InterruptedException e) {};
}
}
};
// A method which updates GUI (sets a new value of JLabel).
private static void updateGUI(final int i, final JLabel label) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
label.setText("You have " + i + " seconds.");
}
}
);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
showGUI();
counter.start();
}
});
}
}
【问题讨论】:
-
@Roman 这里有更详细的讨论:stackoverflow.com/questions/182316/…
-
@Roman 注意: 您的计数器不在 EDT 上启动,它在主线程上启动。计数器通过 updateGUI 方法更新 GUI,该方法在 EDT 上进行更新(因为调用了 invokeLater)。
标签: java user-interface events multithreading invoke