与swingworker的对话是鸡/蛋

时间:2016-06-08 13:16:48

标签: java swingworker

我试图通过不在主线程(EDT)上执行长任务来遵循Java最佳实践。所以我打算使用带有Modal Dialog的swingWorker。这样,模态对话框会阻止用户执行任何操作,直到该任务完成,并且我可以在进程发生时更新对话框的状态。

现在的问题是,使用模态对话框,它不仅会阻止用户,而且在调用setVisible之后也没有任何内容

所以如果我这样做

dialog.setVisible(true);
new SwingWorkerTask().execute(); //This does not get called

如果我这样做

new SwingWorkerTask().execute();
dialog.setVisible(true); // Well what the point of setting visible after the fact.

那么如何在任务发生时阻止用户操作并显示对话框?

谢谢

2 个答案:

答案 0 :(得分:1)

如果你做的话,它只是一只鸡/蛋。您可以在EDT上构建所有Swing对象,然后让Function DrawDiagram() Dim x As Long Dim diaLst As MSForms.ListBox Set diaLst = ActiveSheet.ListBoxes("DiaList") ' find selected trends in List Box For x = 1 To diaLst.ListCount If diaLst.Selected(x) = True Then MsgBox x End If Next x End Function (或任何其他线程)管理所有更新,方法是指示EDT通过SwingUtilities.invokeLater(Runnable)执行它们。

SwingWorker

如果您担心可能会在import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JProgressBar; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; public class RudeProgressBar extends JFrame { private JButton button; public RudeProgressBar() { setTitle("Rude Progress Bar"); setDefaultCloseOperation(EXIT_ON_CLOSE); setLayout(new BorderLayout()); button = new JButton("Do teh work"); add(button, BorderLayout.SOUTH); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JDialog dialog = new JDialog(RudeProgressBar.this, true); dialog.setTitle("Doing teh work"); dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); final JProgressBar progressBar = new JProgressBar(0, 100); dialog.setLayout(new BorderLayout()); dialog.add(progressBar); dialog.setSize(100, 100); dialog.setLocationRelativeTo(RudeProgressBar.this); MyTask task = new MyTask(dialog); task.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if ("progress".equals(evt.getPropertyName())) { progressBar.setValue((Integer)evt.getNewValue()); } } }); task.execute(); } }); setSize(200, 200); setLocationRelativeTo(null); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new RudeProgressBar().setVisible(true); } }); } private class MyTask extends SwingWorker<Void, Void> { private final JDialog dialog; public MyTask(JDialog dialog) { this.dialog = dialog; } @Override protected Void doInBackground() throws Exception { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { dialog.setVisible(true); } }); int progress = 0; for (int i = 0; i < 5; i++) { Thread.sleep(1000); setProgress(progress += 20); } return null; } @Override protected void done() { dialog.setVisible(false); dialog.dispose(); } } } 之后执行invokeLater实施(SwingWorker.doInBackground内),只需将SwingWorker.done中的代码放入另一个done即可。通过执行此操作,您可以将EDT的invokeLater实现排入队列,以便按特定顺序执行它们。即使从EDT本身调用此方法,也会发生排队。

请注意,如果您查看Runnable实施,您会发现它依赖于javax.swing.Timer来执行SwingWorkerdone()本身会调用{ {1}},因此再次在Timer内调用它无关紧要。但是,如果你这样做,那就没有错。

答案 1 :(得分:0)

您可以尝试SwingUtilities.invokeLaterSwingUtilities.invokeAndWait而不是swingWorker。

此外,this topic可能有用。