我一直在使用以下方法创建组件并从Swing返回到EDT外部的值。例如,以下方法可以是JFrame
的扩展,以创建JPanel
并将其添加到父JFrame
:
public JPanel threadSafeAddPanel() {
final JPanel[] jPanel = new JPanel[1];
try {
EventQueue.invokeAndWait(new Runnable() {
public void run() {
jPanel[0] = new JPanel();
add(jPanel[0]);
}
});
} catch (InterruptedException ex) {
} catch (InvocationTargetException ex) {
}
return jPanel[0];
}
本地1长度数组用于从Runnable
内部传输“结果”,该结果在EDT中调用。嗯,它看起来“有点”hacky,所以我的问题:
答案 0 :(得分:3)
虽然这种方法在某些情况下可能有意义,但大部分时间都没用。
原因是由于用户操作(菜单项或点击按钮)总是从EDT执行,因此大多数(如果不是全部)组件的创建将始终从EDT发生。
如果您在创建面板之前需要执行大量工作并且不想阻止EDT,那么您应该按照其他人的建议使用SwingWorker或Swing框架来支持长任务(通常内部基于SwingWorker,但不一定。)
关于你的问题2,遗憾的是你没有很多方法可以做到这一点:
这是简化的ItemHolder类:
public class ItemHolder<T> {
public void set(T item) {...}
public T get() {...}
private T item;
}
答案 1 :(得分:1)
Runnable
SwingWorker
答案 2 :(得分:0)
invokeAndWait
调用//此行添加到安抚降价
public JPanel threadSafeAddPanel() {
final JPanel jPanel = new JPanel();
try {
EventQueue.invokeAndWait(new Runnable() {
public void run() {
add(jPanel);
}
});
} catch (InterruptedException ex) {
} catch (InvocationTargetException ex) {
}
return jPanel;
}
答案 3 :(得分:0)
您可以轻松检查当前线程是否为EDT,然后在该上下文中更准确地执行。至于使用final数组获取返回值,这是必须使用这样的匿名内部类的最简单方法。
public JPanel threadSafeAddPanel() throws InterruptedException,
InvocationTargetException {
if (EventQueue.isDispatchThread()) {
JPanel panel = new JPanel();
add(panel);
return panel;
} else {
final JPanel[] jPanel = new JPanel[1];
EventQueue.invokeAndWait(new Runnable() {
public void run() {
jPanel[0] = new JPanel();
add(jPanel[0]);
}
});
return jPanel[0];
}
}