我目前的代码如下:
final String[] value = new String[1];
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
value[0] = textArea.getText();
}
});
最终阵列的使用看起来有点像黑客。有更优雅的解决方案吗?
我已经做了很多搜索,但我似乎无法找到任何可以做到的事情,这让我感到惊讶。虽然我一直遇到SwingWorker
,但我不确定这种情况是否合适?
我假设JTextArea.getText()
不是线程安全的。
感谢。
答案 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