递归复制文件时,我无法让 Swingworker 工作。无论我做什么,直到复制所有文件后我的进度条才会更新。我选择做的方向是计算文件总数。然后,我有一个 JLabel,列出了从文件总数中复制的文件数。然后我想要一个进度条来显示复制文件的百分比。
这是我当前的代码(非常基本的应用程序,我知道)
package swingworkertest;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.SwingWorker;
public class App extends JFrame {
private JPanel mainPanel;
private JButton button;
private JLabel label;
private JProgressBar progress;
private int totalFiles = 0;
private int copiedFiles = 0;
private void getTotalFiles(File src) {
String[] files = src.list();
for (int i = 0; i < files.length; i++) {
if (new File(src + "\\" + files[i]).isDirectory()) {
getTotalFiles(new File(src + "\\" + files[i]));
} else {
totalFiles++;
}
}
}
private void copyFiles(File src, File dst) throws IOException {
String[] files = src.list();
for (int i = 0; i < files.length; i++) {
if (new File(src + "\\" + files[i]).isDirectory()) {
if (Files.notExists(new File(dst + "\\" + files[i]).toPath(), LinkOption.NOFOLLOW_LINKS)) {
new File(dst + "\\" + files[i]).mkdir();
}
copyFiles(new File(src + "\\" + files[i]), new File(dst + "\\" + files[i]));
} else {
Files.copy(new File(src + "\\" + files[i]).toPath(), new File(dst + "\\" + files[i]).toPath());
copiedFiles++;
label.setText("Files Copied: " + copiedFiles + "/" + totalFiles);
}
}
}
private void setProgress(int value) {
progress.setValue(value);
}
public App(String title) {
this.setTitle(title);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String src = "C:\\Users\\Vinny\\Desktop\\workingDirectory";
String dst = "C:\\Users\\Vinny\\Desktop\\copyToHere";
mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
button = new JButton("Copy");
label = new JLabel("Files Copied: 0/0");
progress = new JProgressBar();
progress.setStringPainted(true);
button.addActionListener((e) -> {
getTotalFiles(new File(src));
System.out.println(totalFiles);
SwingWorker<Boolean, Integer> worker = new SwingWorker<>() {
@Override
protected Boolean doInBackground() throws Exception {
// Background Work
copyFiles(new File(src), new File(dst));
publish(copiedFiles);
// Value transmitted to done()
return true;
}
@Override
protected void process(List<Integer> chunks) {
// Process results
for (int n : chunks) {
int percentage = (int)(n * 100 / totalFiles);
setProgress(percentage);
}
}
@Override
protected void done() {
// Finish sequence
System.out.println("Files Copied");
}
};
worker.execute();
while (!worker.isDone()) {
int percentage = (int)(copiedFiles * 100 / totalFiles);
setProgress(percentage);
}
});
mainPanel.add(button);
mainPanel.add(label);
mainPanel.add(progress);
this.add(mainPanel);
this.pack();
this.setVisible(true);
}
}
这几乎肯定是问题所在。
worker.execute();
while (!worker.isDone()) {
int percentage = (int)(copiedFiles * 100 / totalFiles);
setProgress(percentage);
}
您正在更新 EDT 的进度。基本上,该循环会占用 UI 线程,而不是让它执行其他工作。如果您希望 EDT 能够实际执行,您必须从后台线程进行更新。