从EDT外部获取Swing组件的值

时间:2009-11-07 21:17:41

标签: java swing event-dispatch-thread

我目前的代码如下:

final String[] value = new String[1];

SwingUtilities.invokeAndWait(new Runnable() {
    public void run() {
        value[0] = textArea.getText();
    }
});

最终阵列的使用看起来有点像黑客。有更优雅的解决方案吗?

我已经做了很多搜索,但我似乎无法找到任何可以做到的事情,这让我感到惊讶。虽然我一直遇到SwingWorker,但我不确定这种情况是否合适?

我假设JTextArea.getText()不是线程安全的。

感谢。

3 个答案:

答案 0 :(得分:3)

所有问题都可以通过添加另一层间接来解决(除非有太多层:P)。

public class TextSaver implements Runnable
{
    private final JTextArea textArea;
    private final ObjectToSaveText saveHere;

    public TextSaver(JTextArea textArea, ObjectToSaveText saveHere)
    {
        this.textArea = textArea;
        this.saveHere = saveHere;
    }

    @Override
    public void run()
    {
        saveHere.save(textArea.getText());
    }
}

我不打算提供ObjectToSaveText的代码,但是你明白了。 然后您的SwingUtilties呼叫变为:

SwingUtilities.invokeAndWait(new TextSaver(textArea, saveHere));

您可以从saveHere对象中检索已保存的文本。

答案 1 :(得分:1)

我发现在99%的Swing代码中,我经常访问JTextArea以响应用户操作(用户输入,单击按钮,关闭窗口等)。所有这些事件都是通过事件监听器来处理的,这些监听器总是在EDT上执行。

您能否在用例中提供更多详细信息?

基于使用案例的更新:用户可以在服务器启动后更改文本吗?如果是,那么您可以使用前面提到的侦听器样式。请务必小心你的并发性。如果用户无法更改文本,请将文本传递给服务器线程以响应按钮单击(将在EDT上)并禁用文本框。

最后更新:

如果客户端连接是持久的并且服务器继续发送更新,则可以使用侦听器模型。如果不是,则两份数据副本可能是多余的。无论哪种方式,我认为你最终会有更多的线程工作(除非你使用选择器),而不是担心复制一个数据值。

我认为你现在有很多信息,祝你好运。

答案 2 :(得分:0)

我遇到了同样的需求,获取swing组件值,但是从我的应用程序中调用javascript引擎。我打了下面的实用方法。

/**
 * Executes the specified {@link Callable} on the EDT thread. If the calling
 * thread is already the EDT thread, this invocation simply delegates to
 * call(), otherwise the callable is placed in Swing's event dispatch queue
 * and the method waits for the result.
 * <p>
 * @param <V> the result type of the {@code callable}
 * @param callable the callable task
 * @return computed result
 * @throws InterruptedException if we're interrupted while waiting for the
 * event dispatching thread to finish executing doRun.run()
 * @throws ExecutionException if the computation threw an exception
 */
public static <V> V getFromEDT(final Callable<V> callable) throws InterruptedException, ExecutionException {
    final RunnableFuture<V> f = new FutureTask<>(callable);

    if (SwingUtilities.isEventDispatchThread()) {
        f.run();
    } else {
        SwingUtilities.invokeLater(f);
    }

    return f.get();
}

我相信你可以弄清楚如何使用它,但我想展示它在Java 8中的特别简洁:

String text = <String>getFromEDT(() -> textarea.getText());

修改:更改方法以执行safe publication