如果没有自定义对话框面板中的Thread.sleep(),SwingWorker不会更新JProgressBar

我有一个SwingWorker类,它加载一个文本文件并将其切片到块进行进一步处理。

这是SwingWorker类:

 public class ConverterWorker extends SwingWorker { private final File f; private final JLabel label; public ConverterWorker(File f, JLabel label) { this.f = f; this.label = label; } @Override protected String doInBackground() throws Exception { NMTMain.convertableData = getDataSets(f); if(!NMTMain.convertableData.isEmpty()) { return "Done"; } else { publish("Failed to load the file!"); return "Failed"; } } @Override public void done() { try { label.setText(get()); } catch (Exception e) { e.printStackTrace(System.err); System.out.println("error"); } } @Override protected void process(List chunks) { label.setText(chunks.get(chunks.size() - 1)); } public ArrayList<ArrayList> getDataSets(File f) { ArrayList<ArrayList> dataSets = new ArrayList<ArrayList>(); publish("Loading file..."); setProgress(0); String[] data = loadFile(f); for(int i = 0; i< NMTMain.nodes.size(); i++) { dataSets.add(splitByNode(data, NMTMain.nodes.get(i).getName())); } setProgress(100); return dataSets; } private ArrayList splitByNode(String[] data, String name) { ArrayList temp = new ArrayList(); for(int i = 0; i < data.length; i++) { if(data[i].contains(name)) { temp.add(new Convertable(data[i])); } } Collections.sort(temp); return temp; } private String[] loadFile(File f) { String data = ""; String[] nodes; long fileLength = f.length(); int bytesRead = -1; int totalBytesRead = 0; try { if(f.exists()) { Scanner scan = new Scanner(f); while(scan.hasNextLine()) { String line = scan.nextLine(); data = data + line + "\n"; bytesRead = line.getBytes().length; totalBytesRead += bytesRead; int progress = (int) Math.round(((double) totalBytesRead / (double) fileLength) * 100d); /* try { Thread.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }*/ //publish("loading... " + String.valueOf(progress)); setProgress(progress); } scan.close(); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } nodes = data.split("\n\"\n"); return nodes; } 

这在Thread.sleep(1);时工作正常Thread.sleep(1); 没有评论。 但是,当我评论Thread.sleep(1); 该类不会更新进度条。

我把我的class级称为按钮,这里是ActionListener

 loadInput.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { int returnval=NMTMain.fileChooser.showOpenDialog(NMTMain.MainFrame); if(returnval == 0) { File f=NMTMain.fileChooser.getSelectedFile(); final ConverterWorker worker = new ConverterWorker(f, dialogPanel.getLabel()); worker.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(final PropertyChangeEvent evt) { if("progress".equalsIgnoreCase(evt.getPropertyName())) { dialogPanel.showProgressDialog("Conversion"); dialogPanel.setProgressBarValue((int) evt.getNewValue()); } if(worker.isDone()) { dialogPanel.showConfirmDialog("Conversion", "OK"); } } }); worker.execute(); } } }); 

这应该可以在没有睡眠的情况下正常工作,那么我在这里做错了什么呢?

更新:

事实certificate我的DialogPanel不是最好的,并导致这种行为。

这是DialogPanel类:

 public class DialogPanel extends JDialog { private JLabel label; private JPanel panel; private JButton button; private JProgressBar progressBar; public DialogPanel() { GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = new Insets(5,10,5,10); panel = new JPanel(); panel.setLayout(new GridBagLayout()); progressBar = new JProgressBar(0,100); progressBar.setVisible(false); progressBar.setStringPainted(true); setLabel(new JLabel("def text", SwingConstants.CENTER)); button = new JButton("OK"); button.setVisible(false); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub dispose(); } }); gbc.gridx = 0; gbc.gridy = 0; panel.add(getLabel(), gbc); gbc.gridy = 1; panel.add(progressBar, gbc); panel.add(button, gbc); this.setContentPane(panel); this.setLocationRelativeTo(null); this.setModalityType(Dialog.ModalityType.APPLICATION_MODAL); this.setResizable(false); } public void setProgressBarValue(int value) { progressBar.setValue(value); } public void setProgressBarVisibility(boolean value) { progressBar.setVisible(value); } public void setText(String text) { getLabel().setText(text); } public void showProgressDialog(String title) { progressBar.setVisible(true); button.setVisible(false); this.setTitle(title); this.pack(); if(!this.isVisible()) { this.setVisible(true); } } public void showConfirmDialog(String title, String buttontext) { progressBar.setVisible(false); button.setVisible(true); this.setTitle(title); button.setText(buttontext); this.pack(); if(!this.isVisible()) { this.setVisible(true); } } public JLabel getLabel() { return label; } public void setLabel(JLabel label) { this.label = label; } public JProgressBar getProgressBar() { return progressBar; } @Override public Dimension getPreferredSize() { return new Dimension(200, 100); } } 

对于专业人士来说,这可能是一团糟。 如何在对话框中显示进度条,该对话框将在完成此过程后有一个确认按钮来处理对话框?

解:

我已经从我的DialogPanel类更改为ProgressMonitor ,现在一切都很好。 感谢您的时间和建议。

setProgress() API指出:“出于性能目的,所有这些调用都只合并为一个调用,只有最后一个调用参数。” 添加Thread.sleep(1)只是推迟了合并; 调用println()引入了类似的延迟。 请记住您的文件系统如此之快; 我不愿意引入人为延迟。 作为说明效果的具体示例,我在此完整示例中添加了中间报告,如下所示。

 private static class LogWorker extends SwingWorker { private long fileLength; private long bytesRead; ... this.fileLength = file.length(); ... while ((s = br.readLine()) != null) { publish(s); bytesRead += s.length(); int progress = (int)(100 * bytesRead / fileLength); // System.out.println(progress); setProgress(progress); } ... } lw.addPropertyChangeListener((PropertyChangeEvent e) -> { if ("progress".equals(e.getPropertyName())) { jpb.setValue((Integer)e.getNewValue()); } if ("state".equals(e.getPropertyName())) { SwingWorker.StateValue s = (SwingWorker.StateValue) e.getNewValue(); if (s.equals(SwingWorker.StateValue.DONE)) { jpb.setValue(100); } } }); 

我想在JDialog使用JProgressBar跟踪我的SwingWorker的进度。 但是我的SwingWorker类无法处理我的自定义DialogPanel类。 要获得相同的结果,使用默认的ProgressMonitor类是最佳选择。

我已通过其构造函数将ProgressMonitor传递给SwingWorker

 private final File f; private final ProgressMonitor pm public FileLoadWorker(File f, ProgressMonitor pm) { this.f = f; this.pm = pm; } 

并更改了以下方法:

 @Override public void done() { try { pm.setNote(get()); } catch (Exception e) { e.printStackTrace(System.err); System.out.println("error"); } } @Override protected void process(List chunks) { pm.setNote(chunks.get(chunks.size() - 1)); } 

任务的propertyChangeListener改变如下:

 final FileLoadWorker worker = new FileLoadWorker(f, pm); worker.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(final PropertyChangeEvent evt) { if("progress".equalsIgnoreCase(evt.getPropertyName())) { pm.setProgress((int) evt.getNewValue()); } if("state".equals(evt.getPropertyName())) { SwingWorker.StateValue s = (SwingWorker.StateValue) evt.getNewValue(); if(s.equals(SwingWorker.StateValue.DONE)) { pm.setProgress(100); pm.close(); Toolkit.getDefaultToolkit().beep(); } } if(pm.isCanceled()) { pm.close(); worker.cancel(true); } } }); worker.execute(); 

感谢trashgod的回答和对state财产的评论。