使用invokeAndWait从Swing返回值

时间:2010-03-08 13:34:58

标签: java swing event-dispatch-thread invokeandwait

我一直在使用以下方法创建组件并从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,所以我的问题:

  1. 这有意义吗?还有其他人在做这样的事吗?
  2. 1长数组是转换结果的好方法吗?
  3. 有更简单的方法吗?

4 个答案:

答案 0 :(得分:3)

虽然这种方法在某些情况下可能有意义,但大部分时间都没用。

原因是由于用户操作(菜单项或点击按钮)总是从EDT执行,因此大多数(如果不是全部)组件的创建将始终从EDT发生。

如果您在创建面板之前需要执行大量工作并且不想阻止EDT,那么您应该按照其他人的建议使用SwingWorker或Swing框架来支持长任务(通常内部基于SwingWorker,但不一定。)

关于你的问题2,遗憾的是你没有很多方法可以做到这一点:

  • 像你一样使用1项数组,就是这样 最简单但也是最丑陋的解决方案
  • 创建一个ItemHolder类(请参阅 下面)几乎一样, 需要更多的工作,是 更清洁,在我看来
  • 最后,使用java.util.concurrent 设施(未来和可赎回); 我认为这将是最干净的, 但也需要付出最大努力

这是简化的ItemHolder类:

public class ItemHolder<T> {
    public void set(T item) {...}
    public T get() {...}
    private T item;
}

答案 1 :(得分:1)

  • 在没有记录它们的情况下吞下异常:糟糕!! - 当你在2小时的追捕后发现类似的东西时,你会讨厌自己
  • 不,阵列不是一个好方法;首先,它没有提供简单的方法让调用代码在获取结果之前等待EDT线程执行Runnable
  • 有一个明确为此类设计的课程:SwingWorker

答案 2 :(得分:0)

  1. a)这是有道理的。 b)不是我所知道的。
  2. 和任何人一样好。
  3. invokeAndWait调用
  4. 之外创建JPanel

    //此行添加到安抚降价

    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];
    }
}