【发布时间】:2013-01-08 12:31:56
【问题描述】:
我是摇摆新手,仍在学习它的来龙去脉。我编写了一个基本代码并开始尝试使用 EDT。代码如下:
public class SwingDemo2 extends Thread implements ActionListener {
JLabel jl;
SwingDemo2() {
JFrame jfr = new JFrame("Swing Event Handling");
jfr.setSize(250, 100);
jfr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jl = new JLabel("Press a button!", SwingConstants.CENTER);
System.out.println("After Label: " + SwingUtilities.isEventDispatchThread());
JButton jb1 = new JButton("OK");
jb1.setActionCommand("OK");
jb1.addActionListener(this);
JButton jb2 = new JButton("Reset");
jb2.setActionCommand("Reset");
jb2.addActionListener(this);
jfr.add(jl, BorderLayout.NORTH);
jfr.add(jb1, BorderLayout.WEST);
jfr.add(jb2, BorderLayout.EAST);
System.out.println("After adding: " + SwingUtilities.isEventDispatchThread());
jfr.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
System.out.println("In main: " + SwingUtilities.isEventDispatchThread());
new SwingDemo2();
}
});
}
public void actionPerformed(ActionEvent ae) {
if (ae.getActionCommand() == "OK") {
System.out.println("In OK: " + SwingUtilities.isEventDispatchThread());
jl.setText("You pressed Ok");
}
else if (ae.getActionCommand() == "Reset") {
System.out.println("In Reset: " + SwingUtilities.isEventDispatchThread());
jl.setText("You pressed Reset");
}
}
}
我添加了一些isEventDispatchThread() 方法来验证我所在的线程。
除了 GUI,控制台中的消息还有:
In main: true
After Label: true
After adding: true
In OK: true
In Reset: true
似乎我一直在 EDT。我的问题是,在 jfr.setVisible(true) 语句之后,SwingDemo2() 构造函数不应该返回到 main() 并且不应该是 EDT 的结束吗?
在我第一次按下 GUI 中的任何按钮之前,我等了好几秒钟,那么为什么我的事件处理仍在 EDT 中完成?这不应该给 EDT 足够的时间来终止吗?
提前谢谢!
【问题讨论】:
-
试着在
invokeLater()之外写一个isEventDispatchThread(),在你的main方法中,你会明白他们是多么的分开。当 Swing 应用程序运行时,会启动三个线程。 1。主线程: 您的应用程序从该线程运行。 2。工具包线程: 该线程负责捕获系统事件,例如键盘按键或鼠标移动。虽然,这个线程从不运行应用程序代码。捕获的事件被传递到第三个线程,即 EDT。 3。 EDT - Event Dispatch Thread: 负责调度工具包线程捕获的事件。 -
EDT 是您与 Swing 交互的线程。
-
@GagandeepBali 另一个愚蠢的问题: Swing 应用程序有多少个 EDT?当我尝试在已经存在的之后调用
invokeLater再次时,程序编译并运行完美。它是在同一个 EDT 中运行还是创建了一个新的? -
No
invokeLater()实际上是用来将你的新任务放在同一个EDT上。还有一种称为invokeAndWait()的方法,尽管它会将任务放在EDT 上,并等到该任务未完成。因此它会在这段时间内阻塞EDT,直到任务没有完成。这个使用起来有点棘手,因为如果使用不当,它可能会导致deadlocks/run conditions。 -
每当创建新任务时,您只需使用
invokeLater()将该任务放在EDT queue上,它根据FIFOAFAIK 原则执行任务。
标签: java multithreading swing event-handling event-dispatch-thread