Все тяжелые задачи в Swing должны выполняться SwingWorkers .В противном случае большая задача будет затруднять работу Thread Dispatch Thread , поэтому события не могут происходить (графический интерфейс остановится).
Итак, вам нужно создать SwingWorker
и вычислитьВыполните шаги задачи в процентах и присвойте значение индикатору выполнения.Однако вы должны иметь в виду, что, поскольку progressbar.setValue(int value)
является обновлением компонента, оно должно происходить только внутри EDT.Вот почему вы должны использовать publish
и process
методы работника.
Давайте рассмотрим пример, в котором мы должны записать 1000 строк в текстовый файл в Desktop и увидеть его прогресс.Это «большая задача» (я сплю), так что она соответствует нашему случаю.
public class ProgressExample extends JFrame {
private static final long serialVersionUID = 5326278833296436018L;
public ProgressExample() {
super("test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(new ProgressPanel());
pack();
setLocationRelativeTo(null);
}
private static class WriteTextWorker extends SwingWorker<Void, Integer> {
private ProgressableView view;
public WriteTextWorker(ProgressableView view) {
this.view = view;
}
@Override
protected void process(List<Integer> chunks) {
int progress = chunks.get(0);
view.setProgress(progress);
}
@Override
protected Void doInBackground() throws Exception {
publish(0);
File desktop = new File(System.getProperty("user.home"), "Desktop");
File textFile = new File(desktop, "stackoverflow.txt");
int linesToWrite = 1000;
try (FileWriter fw = new FileWriter(textFile, true);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter out = new PrintWriter(bw)) {
for (int i = 0; i < linesToWrite; i++) {
out.println("This is line: " + i);
out.flush();
//Calculate percentage of completed task
int percentage = ((i * 100) / linesToWrite);
System.out.println("Percentage: " + percentage);
publish(percentage);
Thread.sleep(10); //Heavy task
}
}
return null;
}
}
private static class ProgressPanel extends JPanel implements ProgressableView {
private JProgressBar progressBar;
private SwingWorker<Void, Integer> worker;
public ProgressPanel() {
super(new BorderLayout());
progressBar = new JProgressBar();
add(progressBar, BorderLayout.PAGE_START);
JButton writeLinesButton = new JButton("Press me to do a long task");
writeLinesButton.addActionListener(e -> worker.execute());
add(writeLinesButton, BorderLayout.PAGE_END);
worker = new WriteTextWorker(this);
}
@Override
public int getProgress() {
return progressBar.getValue();
}
@Override
public void setProgress(int progress) {
progressBar.setValue(progress);
}
}
public static interface ProgressableView {
int getProgress();
void setProgress(int progress);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new ProgressExample().setVisible(true));
}
}