与swingworker的对话是鸡/蛋
我试图通过不在主线程(EDT)上执行长任务来遵循Java最佳实践。 所以我打算使用带有Modal Dialog的swingWorker。 这样,modal dialog阻止用户执行任何操作,直到该任务完成,并且我可以在进程发生时更新对话框的状态。
现在的问题是,使用modal dialog,它不仅会阻止用户,而且在调用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.
那么如何在任务发生时阻止用户操作并显示对话框?
谢谢
如果你做到这一点,它只是一个鸡/蛋。 您可以在EDT上构造所有Swing对象,然后让SwingWorker
(或任何其他线程)通过指示EDT通过SwingUtilities.invokeLater(Runnable)
执行它们来管理所有更新。
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 { 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(); } } }
如果您担心在SwingWorker.doInBackground
之后可能会执行invokeLater
实现(在SwingWorker.doInBackground
),只需将代码放入另一个invokeLater
。 通过执行此操作,您可以对EDT的Runnable
实现进行排队,以便按特定顺序执行它们。 即使从EDT本身调用此方法,也会发生排队。
请注意,如果你看看SwingWorker
实现,你会发现它依赖于javax.swing.Timer
来执行done()
而Timer
本身调用了invokeLater
,所以再次调用它就done
了什么。 但是,如果你这样做,那就什么都不会错。
您可以尝试使用SwingUtilities.invokeLater和SwingUtilities.invokeAndWait而不是swingWorker。
此外, 该主题可能有用。
- 是否更好地使用getter方法或在覆盖toString时直接访问私有字段?
- 为什么POST不尊重charset,但是AJAX请求呢? tomcat 6
- Maven是否支持增量构建?
- 无法使用java SoapMessage更改信封中的soap URI
- 会话中的Spring存储对象
- 如何在我的应用程序的java fx 2.0中更改舞台标题栏上的图标
- SSL握手exception:“算法约束检查失败:MD5withRSA”
- 将Integers与==进行比较究竟做了什么?
- 线程“main”中的exceptionjava.lang.UnsatisfiedLinkError:资源路径中找不到jnidispatch(/ com / sun /jna/win32-x86/jnidispatch.dll)