我一直在关注这个帖子,尝试从我的程序中的一个单独的类更新JProgressBar:java - Progress Bar - Is it possible to use setProgess() of Progress Bar outside the doInBackground() method?
不幸的是我的代码无法正常工作。我可能错过了什么,但我似乎无法弄清楚它是什么。这是我到目前为止编写的代码:
这是我用来更新进度条的propertyChangeListener:
PropertyChangeListener listener = new PropertyChangeListener(){
public void propertyChange(PropertyChangeEvent event){
if("progress".equals(event.getPropertyName())){
progressBar.setValue((int)currentPercent);
progressBar.setString(Integer.toString((int)currentPercent));
}
}
};
SwingWorker类:
class Task extends SwingWorker<Void, String>{
public Task(){
md = new ManipulateDirectories(this);
}
@Override
public Void doInBackground(){
for(int i = 0; i < directories.length; i++){
md.copyDirectory(directories[i], backupDir);
}
return null;
}
@Override
public void process(List<String> chunks){
}
@Override
public void done(){
closeWindow();
}
public void updateProgress(int tick){
setProgress(tick);
}
}
ManipulateDirectories类:
public class ManipulateDirectories{
Task task;
public ManipulateDirectories(Task task){
this.task = task;
}
//Recursive function to loop through and copy individual files
public void copyDirectory(File file, File dest){
if(file.isFile()){
try {
FileUtils.copyFileToDirectory(file, dest);
currentSize = currentSize + getDirSize(file);
if(currentSize >= ONE_PERCENT){
currentPercent = currentPercent + (currentSize / ONE_PERCENT);
task.updateProgress((int)currentPercent); //THIS LINE DOES NOT WORK
currentSize = currentSize % ONE_PERCENT;
}
} catch (IOException e) {
e.printStackTrace();
}
} else if (file.isDirectory()){
File newDir = new File(String.format("%s\\%s", dest.getAbsolutePath(), file.getName()));
if(!newDir.exists()){
newDir.mkdir();
for(File f : file.listFiles()){
copyDirectory(f, newDir);
}
}
}
}
public Long getDirSize(File file) {
long size = 0L;
if (file.isFile() && file != null){
size += file.isDirectory() ? getDirSize(file) : file.length();
} else if (file.isDirectory()){
for (File f : file.listFiles()) {
size += f.isDirectory() ? getDirSize(f) : file.length();
}
}
return size;
}
}
正如您所看到的,propertyChangeListener应该由swingworker类中的updateProgress(int)方法触发,并且该方法应该由ManipulateDirector类中的行task.updateProgress((int)currentPercent)
调用。但是,该行似乎没有调用updateProgress()。我猜它可能是“任务”的特定实例的问题 - 也许我正在创建一个没有正确上下文的单独实例? (我知道术语可能有点不对,但希望你能理解我想说的话)。谁能发现我的错误?任何帮助都会非常感激,我已经坚持了很长一段时间了。
SSCCE:
import java.awt.BorderLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.border.EmptyBorder;
public class MainClass extends JFrame {
private JProgressBar progressBar;
private DoSomething ds;
private int currentPercent = 0;
private Task task;
private static JPanel contentPane;
private JPanel bottomPane;
private JButton btnCancel;
public static void main(String[] args){
MainClass mc = new MainClass();
mc.createGUI();
}
public void createGUI(){
//Create frame
setTitle("Backup Progress");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 350);
//Create content pane
contentPane = new JPanel(new BorderLayout());
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
//Create panel for progress bar/cancel button
bottomPane = new JPanel();
bottomPane.setLayout(new BoxLayout(bottomPane, BoxLayout.Y_AXIS));
progressBar = new JProgressBar(0, 100);
progressBar.setStringPainted(true);
progressBar.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
progressBar.setValue(0);
btnCancel = new JButton("Cancel");
btnCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
closeWindow();
}
});
bottomPane.add(progressBar);
bottomPane.add(btnCancel);
contentPane.add(bottomPane, BorderLayout.SOUTH);
PropertyChangeListener listener = new PropertyChangeListener(){
public void propertyChange(PropertyChangeEvent event){
if("progress".equals(event.getPropertyName())){
progressBar.setValue((int)currentPercent);
progressBar.setString(Integer.toString((int)currentPercent));
}
}
};
setVisible(true);
task = new Task();
task.execute();
}
class Task extends SwingWorker<Void, String>{
public Task(){
ds = new DoSomething(this);
}
@Override
public Void doInBackground(){
for(int i = 0; i < 100; i++){
ds.incrementPercent();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
@Override
public void done(){
closeWindow();
}
public void updateProgress(int tick){
setProgress(currentPercent + tick);
}
}
public class DoSomething{
Task task;
public DoSomething(Task task){
this.task = task;
}
public void incrementPercent(){
task.updateProgress(1);
}
}
public void closeWindow(){
WindowEvent close = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(close);
}
}
我意识到这是一个非常长的SSCCE,但希望它能为您提供您需要知道的所有信息。
答案 0 :(得分:3)
您永远不会将您的听众添加到SwingWorker
。
更改为:
task = new Task();
task.addPropertyChangeListener(listener);
您遇到的另一个错误是您永远不会更新currentPercent
中的updateProgress
。
public void updateProgress(int tick){
currentPercent+=tick;
setProgress(currentPercent);
}
修改强>
实际上,您的错误在您的代码(而不是sscce)中是相同的,您永远不会更新currentPercent
值。
PropertyChangeListener listener = new PropertyChangeListener(){
public void propertyChange(PropertyChangeEvent event){
if("progress".equals(event.getPropertyName())){
currentPercent = (int)event.getNewValue();
progressBar.setValue(currentPercent);
progressBar.setString(Integer.toString(currentPercent));
}
}
};