【发布时间】:2013-12-27 23:52:07
【问题描述】:
我一直在关注这个帖子,试图从我的程序中的一个单独的类中更新一个 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) 方法触发,并且该方法应该由 ManipulateDirectories 类中的 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,但希望它能给你提供你需要知道的所有信息。
【问题讨论】:
-
抱歉,我从来没有注意到添加了swing标签。从现在开始,我会记住这一点。稍后我将整理一份快速的 SSCCE。
-
ONE_PERCENT等于什么,currentSize和currentPercent声明为什么?您的代码 sn-p 真的毫无意义,因为它没有描述足够多的帮助您正在做的事情...... -
糟糕,我忘了包括那个。我最初用一个变量“totalSize”来调用这个类,它是一组目录的总大小。 ONE_PERCENT 是 totalSize/100,它为我提供了进度条增加 1% 所需的大小。 CurrentSize 是已复制文件大小的总和,只要它小于 1%。 CurrentPercent 是应显示在进度条上的总百分比。希望这是有道理的。
-
@AndrewThompson,SSCCE 已添加,尽管它比我希望的要长。希望它足够好,这是我能做的最好的事情
-
根据您的 SSCCE,currentPercent + tick 将始终为 1 ;)
标签: java swing class external updateprogress