【发布时间】:2019-02-02 19:13:53
【问题描述】:
我有一个带有进度条和文本区域的模态 Jdialog。我正在启动一个 Swing Worker 来执行一些后台任务并使用发布过程更新 jdialog 中的文本区域。但是,在运行程序时,我观察到即使调用了 process 方法,它仍然没有更新 jdialog 中的文本区域。另外,请注意,我在 swing worker 的 done 方法中关闭了 jdialog,它工作正常。谁能告诉我为什么没有从(SwingWorker 的)流程方法进行 gui 更新?
JDialog 类 -
public class ProgressDialog extends JDialog {
private static final long serialVersionUID = 1L;
private GridBagLayout gridBag;
private GridBagConstraints constraints;
private ProgressDialog.ProgressBar progressBar;
private JScrollPane scrollPane;
private JTextArea textArea;
ProgressDialog(Frame owner, String title, boolean modal, int numTasks) {
super(owner,title,modal);
gridBag = new GridBagLayout();
constraints = new GridBagConstraints();
this.progressBar = new ProgressDialog.ProgressBar();
this.progressBar.init(numTasks);
this.textArea = new JTextArea(10,30);
this.textArea.setEditable(false);
this.scrollPane = new JScrollPane(this.textArea);
this.scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
this.scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
this.setLayout(gridBag);
constraints.gridx = 0;
constraints.gridy = 0;
gridBag.setConstraints(progressBar, constraints);
constraints.gridx = 0;
constraints.gridy = 1;
constraints.insets = new Insets(10,0,10,0);
gridBag.setConstraints(scrollPane, constraints);
this.add(progressBar);
this.add(scrollPane);
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
this.setSize(400, 300);
this.setLocationRelativeTo(null);
}
class ProgressBar extends JProgressBar {
ProgressBar() {
}
void init(int numTasks) {
setMaximum(numTasks);
setStringPainted(true);
setValue(0);
}
void setProgress(int taskCompleted) {
int totalTasks = getMaximum();
setValue(taskCompleted);
setString(taskCompleted+"/"+totalTasks);
}
}
static long getSerialversionuid() {
return serialVersionUID;
}
GridBagLayout getGridBag() {
return gridBag;
}
GridBagConstraints getConstraints() {
return constraints;
}
ProgressDialog.ProgressBar getProgressBar() {
return progressBar;
}
JScrollPane getScrollPane() {
return scrollPane;
}
JTextArea getTextArea() {
return textArea;
}
}
SwingWorker 类:
public class SwingWorkers {
static class ConnPool extends SwingWorker<Void, TaskType<String>>{
private ProgressDialog pDialog;
ConnPool(ProgressDialog pDialog) {
this.pDialog = pDialog;
}
protected Void doInBackground() throws Exception {
Runner<String> runner = new Runner<>();
Future<TaskType<String>> fut = runner.run(new Tasks.InitResources());
runner.shutDown();
while(!fut.isDone()) {
Thread.sleep(1000);
}
publish(fut.get());
return null;
}
protected void process(List<TaskType<String>> results) {
if(results.size() > 0) {
TaskType<String> lastResult = results.get(results.size()-1);
pDialog.getTextArea().append(lastResult.getTaskStatusMesg());
pDialog.getTextArea().append("\n");
pDialog.getProgressBar().setValue(results.size());
}
}
protected void done() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
pDialog.dispose();
}
}
}
调用 Jdialog 和 Swingworker 的控制器代码 -
JFrame parent = GUI.getInstance().getFrame();
ProgressDialog pDialog = new ProgressDialog(parent,"Working...",false,1);
pDialog.getTextArea().append("Initializing background tasks");
new SwingWorkers.ConnPool(pDialog).execute();
pDialog.setVisible(true);
我在某处读到,一旦模态 Jdialog 可见,EDT 会被阻止直到再次关闭?但这仍然不能解释为什么 SwingWorker 中的 done 方法能够关闭 Jdialog。
编辑: 我知道我只调用一次 process 方法(它应该在一个 while 循环中)。在我可以让这个场景(从流程方法更新 gui)工作之后,我打算使用发布流程机制来完成更耗时的任务。
还要注意 sleep in done 方法仅用于测试。我可以在 done 方法中不使用 sleep 方法来重现相同的问题。
【问题讨论】:
标签: java multithreading swing swingworker