Sto*_*dow 9 java swing multithreading event-dispatch-thread
我读到构造Swing组件和处理事件的所有代码必须由Event Dispatch Thread运行.我理解这是如何通过使用该SwingUtilities.invokeLater()方法完成的.请考虑以下代码,其中GUI初始化在main方法本身中完成
public class GridBagLayoutTester extends JPanel implements ActionListener {
public GridBagLayoutTester() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
JButton button = new JButton("Testing");
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 1;
button.addActionListener(this);
add(button, gbc);
}
public void actionPerformed(ActionEvent e) {
System.out.println("event handler code");
}
public static void main(String[] args) {
JFrame frame = new JFrame("GridBagLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = frame.getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(new GridBagLayoutTester(), BorderLayout.CENTER);
frame.setSize(800, 600);
frame.pack();
frame.setVisible(true);
System.out.println("Exiting");
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码如何完美运行?我们正在JFrame主线程中构造并调用许多其他方法.我不明白EDT在这里的确切位置(执行什么代码?).该方法的构造函数GridBagLayoutTester也是从该main方法调用的,这意味着EDT没有运行它.
简而言之
Eri*_*son 12
代码工作正常,因为您在主线程中构建框架,然后EDT才有机会与之交互.从技术上讲,你不应该这样做,但从技术上讲,你可以在这种特定情况下,因为你不能与JFrame交互,直到它变得可见.
要知道的主要问题是Swing组件不是线程安全的.这意味着它们不能同时从多个线程进行修改.这可以通过确保所有修改都来自EDT来解决.
EDT是一个致力于用户交互的线程.用户生成的任何事件始终在EDT上运行.任何用户界面更新都在EDT上运行.例如,当您调用时Component.repaint(),可以从任何线程调用它.这只是设置一个标志,将组件标记为需要绘画,EDT在下一个周期完成.
EDT自动启动,并与系统实施紧密相关.它在JVM中处理得很好.通常,它与窗口系统中处理用户交互的单个线程相关.当然,这完全取决于实现.好消息是你不必担心这个.您只需要知道 - 如果您与任何Swing组件进行交互,请在EDT上进行.
同样,还有一件事是重要的.如果您要对外部资源进行任何长时间处理或阻止,并且您要响应用户生成的事件而执行此操作,则必须将其安排在EDT自己的线程中运行.如果未能执行此操作,则会在等待长时间处理运行时导致用户界面阻塞.优秀的例子是从文件加载,从数据库读取或与网络交互.您可以使用该方法测试是否在EDT上(对于创建可以从任何线程调用的中性方法很有用)SwingUtilities.isEventDispatchThread().
这里有两段代码,我在编写处理EDT的Swing编程时经常使用这些代码片段:
void executeOffEDT() {
if (SwingUtilities.isEventDispatchThread()) {
Runnable r = new Runnable() {
@Override
public void run() {
OutsideClass.this.executeOffEDTInternal();
}
};
new Thread(r).start();
} else {
this.executeOffEDTInternal();
}
}
void executeOnEDT() {
if (SwingUtilities.isEventDispatchThread()) {
this.executeOnEDTInternal();
} else {
Runnable r = new Runnable() {
@Override
public void run() {
OutsideClass.this.executeOnEDTInternal();
}
};
SwingUtilities.invokeLater(r);
}
}
| 归档时间: |
|
| 查看次数: |
2855 次 |
| 最近记录: |