我对如何正确、安全地将数据从事件分派(dispatch)线程 (EDT) 上的 GUI 元素传递到需要与该数据交互的 SwingWorker 感到困惑。我遵循了 stackoverflow 和网络上的许多示例;无论我尝试以哪种方式编写,似乎都违反了绝不接触不同线程中的 GUI 元素的誓言。
我将尝试用伪代码来说明我的困惑。
我有一个带有一些 Swing 元素的 JFrame 来获取用户的输入。用户单击 JButton,JButton 被禁用,因此用户不能单击它两次,并且他们的输入将传递到后台线程中的 SwingWorker:
import javax.swing.*;
import java.awt.event.*;
class GUI implements Runnable{
JFrame jFrame;
JTextField userInputTextField;
JButton beginLongTaskButton;
GUI(){
//initialize the GUI elements, add them to JFrame, JPanel, etc.
this.beginLongTaskButton = new JButton("Begin Task");
this.beginLongTaskButton.addActionListener(a -> beginLongTask());//lambda sure is nice
}
void beginLongTask(){
this.beginLongTaskButton.setEnabled(false);
this.beginLongTaskButton.setText("Doing your long task...");
LongTaskWorker longTaskWorker = new LongTaskWorker(this.userInputTextField);//isn't this bad?
longTask.execute();
}
@Override
public void run(){
this.jFrame.setVisible(true);//blah blah
}
}
此时,EDT 应该一切正常,除了一个问题:SwingWorker 通过其构造函数获得了一些 GUI 元素:
import javax.swing.*;
class LongTaskWorker extends SwingWorker<Void, Void>{
JTextField userInputTextField;
public LongTaskWorker(final JTextField userInputTextField){
this.userInputTextField = userInputTextField;//the text field on EDT I'm not supposed to touch
}
@Override
protected Void doInBackground() throws Exception{
//read lots of stuff from JTextField in this Thread (the wrong thread)?
//write? lots of stuff to JTextField in this Thread (the wrong thread)?
//do lots of other stuff to JTextField?
return null;
}
}
我见过很多人做类似的事情。我认为即使是 JavaDoc SwingWorker 示例也是这样做的。但这是否意味着我在不应该的情况下弄乱了不同线程上的对象?读取(不更改)GUI 组件的值是否仍然违反跨线程规则?如果我的 SwingWorker 必须频繁地从 GUI 元素读取数据,这不会减慢 EDT 的速度吗?
也许正确的做法是从 EDT 内的 GUI 元素中提取我需要的数据,然后将提取的数据传递给 SwingWorker?与直接将 GUI 元素传递给 SwingWorker 不同。
最佳答案
我认为您实际上可能想要的是您的 View 的模型。也就是说: View 顾名思义就是您的 GUI 及其元素 - JTextFields。您的模型将是 81 个值(value)观的支持 map 。现在,如果您想对其进行计算,您可以将支持 Map 传递给该方法 (SwingWorker)。如果支持模型发生更改,则事件应触发 GUI 刷新(从模型加载值)。如果用户更改 GUI 中的值,则应通过 Controller 进行更改。它依次更改模型并启动更改事件。
这样您还可以避免反馈循环。
您可以通过查找“MVC”或“ Model View Controller ”来了解此概念。
关于java - 如何安全地将用户 GUI 输入数据传递给 SwingWorker 并使用该数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32557334/