JProgressBar 显示另一个 class void 的状态
JProgressBar show status of another class void
我有一个 class 从一个文件夹列表中执行复制的文件,这些文件首先作为 .txt 加载,然后复制到临时文件夹。我想显示将文件复制到文件夹的进度,反之亦然
这是我的副本class:
public class CopyService {
private String _destLocation;
private List<File> _filePaths = new ArrayList<File>();
private Map<String, String> _fileProperties = new HashMap<String, String>();
private String _rootLocation;
private File _txtFile;
public CopyService() {
setRootLocation(NekretnineService.getRootFolder());
setDestLocation(NekretnineService.getDestFolder());
}
public void copyImagesToTempFolder() throws IOException {
File destLocationFolder = new File(getDestLocation());
if (getFilePaths() != null) {
if (!destLocationFolder.exists()) {
destLocationFolder.mkdir();
}
for (File f : getFilePaths()) {
if (f.exists()) {
FileUtils.copyFileToDirectory(f, destLocationFolder);
}
}
}
}
public String getDestLocation() {
return _destLocation;
}
public List<File> getFilePaths() {
return _filePaths;
}
public Map<String, String> getFileProperties() {
return _fileProperties;
}
public String getRootLocation() {
return _rootLocation;
}
public File getTxtFile() {
return _txtFile;
}
public void loadTxtFile(File txtFile) throws Exception {
try {
int lines = 0;
List<String> imgNames = new ArrayList<String>();
try (BufferedReader br = new BufferedReader(new FileReader(txtFile))) {
String txtLine;
while ((txtLine = br.readLine()) != null) {
imgNames.add(txtLine);
lines++;
}
}
for (String img : imgNames) {
String fullPath = getRootLocation();
fullPath += File.separator + img;
getFilePaths().add(new File(fullPath));
fullPath = "";
}
_fileProperties.put("filename", txtFile.getName());
_fileProperties.put("filesize", String.valueOf(txtFile.length()));
_fileProperties.put("totalimgs", String.valueOf(lines));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public void setDestLocation(String destLocation) {
_destLocation = destLocation;
}
public void setFilePaths(List<File> filePaths) {
_filePaths = filePaths;
}
public void setFileProperties(Map<String, String> fileProperties) {
_fileProperties = fileProperties;
}
public void setRootLocation(String rootLocation) {
_rootLocation = rootLocation;
}
public void setTxtFile(File txtFile) {
_txtFile = txtFile;
}
@Override
public String toString() {
return "CopyService [_destLocation=" + _destLocation + ", _filePaths=" + _filePaths + ", _fileProperties="
+ _fileProperties + ", _rootLocation=" + _rootLocation + ", _txtFile=" + _txtFile + "]";
}
}
这是我的 GUI window 使用 window 构建器制作的:
public class MainWindow extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel _contentPane;
private CopyService copyService;
private JLabel lblFileName;
private JLabel lblFileSize;
private JLabel lblImagesCount;
private JTextField txtImgDestination;
private JTextField txtRootLocation;
public MainWindow() {
Image img = new ImageIcon(getClass().getClassLoader().getResource("ico_house.png")).getImage();
setIconImage(img);
setSize(450, 341);
setTitle("Nekretnine Service");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
setLocationRelativeTo(null);
_contentPane = new JPanel();
_contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(_contentPane);
_contentPane.setLayout(null);
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
tabbedPane.setBounds(0, 0, 434, 261);
_contentPane.add(tabbedPane);
JPanel backupTab = new JPanel();
tabbedPane.addTab("Backup", null, backupTab, null);
JPanel imgCleanerTab = new JPanel();
tabbedPane.addTab("Image Cleaner", null, imgCleanerTab, null);
imgCleanerTab.setLayout(null);
JPanel panel = new JPanel();
panel.setBorder(new BevelBorder(BevelBorder.LOWERED, Color.BLACK, null, null, null));
panel.setBounds(10, 11, 409, 73);
imgCleanerTab.add(panel);
panel.setLayout(null);
lblFileName = new JLabel("Filename:");
lblFileName.setBounds(20, 11, 247, 14);
panel.add(lblFileName);
lblFileName.setFont(new Font("Tahoma", Font.BOLD, 11));
lblFileSize = new JLabel("Size:");
lblFileSize.setBounds(20, 30, 247, 14);
panel.add(lblFileSize);
lblFileSize.setFont(new Font("Tahoma", Font.BOLD, 11));
lblImagesCount = new JLabel("Total images to copy:");
lblImagesCount.setBounds(20, 49, 247, 14);
panel.add(lblImagesCount);
lblImagesCount.setFont(new Font("Tahoma", Font.BOLD, 11));
JButton btnCopyBack = new JButton("Copy to location");
btnCopyBack.setEnabled(false);
btnCopyBack.setFont(new Font("Tahoma", Font.PLAIN, 12));
btnCopyBack.setBounds(10, 165, 200, 23);
imgCleanerTab.add(btnCopyBack);
JButton btnDelete = new JButton("Clean images folder");
btnDelete.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
btnCopyBack.setEnabled(true);
}
});
btnDelete.setEnabled(false);
btnDelete.setFont(new Font("Tahoma", Font.PLAIN, 12));
btnDelete.setBounds(10, 131, 200, 23);
imgCleanerTab.add(btnDelete);
JButton btnCopyImagesToTemp = new JButton("Copy images to temp folder");
btnCopyImagesToTemp.setEnabled(false);
btnCopyImagesToTemp.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
copyService.copyImagesToTempFolder();
btnDelete.setEnabled(true);
} catch (IOException e1) {
JOptionPane.showMessageDialog(_contentPane, "File error " + e1.getMessage(), "Error",
JOptionPane.ERROR_MESSAGE);
}
}
});
btnCopyImagesToTemp.setFont(new Font("Tahoma", Font.PLAIN, 12));
btnCopyImagesToTemp.setBounds(10, 97, 200, 23);
imgCleanerTab.add(btnCopyImagesToTemp);
JButton btnFileList = new JButton("Images List");
btnFileList.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new FileList(copyService.getFilePaths()).setVisible(true);
}
});
btnFileList.setEnabled(false);
btnFileList.setBounds(276, 7, 123, 23);
panel.add(btnFileList);
JButton btnLoadTxtFile = new JButton("Load .txt File");
btnLoadTxtFile.addActionListener(new ActionListener() {
@SuppressWarnings("static-access")
public void actionPerformed(ActionEvent e) {
try {
JFileChooser jf = new JFileChooser("C:\");
FileNameExtensionFilter filter = new FileNameExtensionFilter("TEXT FILES", "txt", "text");
jf.setFileFilter(filter);
int status = jf.showOpenDialog(_contentPane);
if (status == jf.APPROVE_OPTION) {
copyService = new CopyService();
copyService.loadTxtFile(jf.getSelectedFile());
lblFileName.setText("Filename:" + " " + copyService.getFileProperties().get("filename"));
lblFileSize.setText("Size:" + " " + copyService.getFileProperties().get("filesize") + " b");
lblImagesCount.setText(
"Total images to copy:" + " " + copyService.getFileProperties().get("totalimgs"));
btnFileList.setEnabled(true);
btnCopyImagesToTemp.setEnabled(true);
} else {
JOptionPane.showMessageDialog(_contentPane, "Error while choosing file", "Error",
JOptionPane.ERROR_MESSAGE);
}
} catch (Exception e1) {
JOptionPane.showMessageDialog(_contentPane, "File error " + e1.getMessage(), "Error",
JOptionPane.ERROR_MESSAGE);
}
}
});
btnLoadTxtFile.setBounds(277, 45, 123, 23);
panel.add(btnLoadTxtFile);
JProgressBar progressBar = new JProgressBar();
progressBar.setBounds(10, 199, 409, 23);
imgCleanerTab.add(progressBar);
JPanel confifgTab = new JPanel();
tabbedPane.addTab("Settings", null, confifgTab, null);
confifgTab.setLayout(null);
JButton btnSaveSettings = new JButton("Save Settings");
btnSaveSettings.setFont(new Font("Tahoma", Font.BOLD, 12));
btnSaveSettings.setBounds(294, 202, 125, 20);
confifgTab.add(btnSaveSettings);
txtRootLocation = new JTextField();
txtRootLocation.setEditable(false);
txtRootLocation.setBounds(10, 34, 259, 20);
confifgTab.add(txtRootLocation);
txtRootLocation.setColumns(10);
JLabel lblNewLabel = new JLabel("Root folder for images:");
lblNewLabel.setBounds(10, 11, 140, 14);
confifgTab.add(lblNewLabel);
JButton btnSelectRootFolder = new JButton("Select Folder");
btnSelectRootFolder.setBounds(279, 33, 140, 23);
confifgTab.add(btnSelectRootFolder);
txtImgDestination = new JTextField();
txtImgDestination.setEditable(false);
txtImgDestination.setColumns(10);
txtImgDestination.setBounds(10, 88, 259, 20);
confifgTab.add(txtImgDestination);
JLabel lblDestinationFolderFor = new JLabel("Destination folder for images:");
lblDestinationFolderFor.setBounds(10, 65, 259, 14);
confifgTab.add(lblDestinationFolderFor);
JButton btnSelectDestFolder = new JButton("Select Folder");
btnSelectDestFolder.setBounds(279, 87, 140, 23);
confifgTab.add(btnSelectDestFolder);
}
public JTextField getTxtImgDestination() {
return txtImgDestination;
}
public JTextField getTxtRootLocation() {
return txtRootLocation;
}}
想在进度条上显示复制进度,不知道怎么实现,只知道while复制方法和gui一样class
您将希望允许外部 classes 在复制文件时监听 CopyService class 状态的变化,但幸运的是 Java 和 Swing 具有用于这个,但是你需要付出一些努力来学习如何使用这些库。建议:
- 给CopyServiceclass一个SwingPropertyChangeSupport私有实例字段,初始化实例,传入
this
,当前class。该对象具有允许其接受侦听器的机制,然后您作为编码人员可以通过调用其方法将 class 中的状态更改通知这些侦听器。
- 为 class 提供一个
public void addPropertyChangeListener(PropertyChangeListener l)
委托方法,并在该方法内将侦听器添加到 SwingPropertyChangeSupport 实例。
- 给class一个public常量字符串,比如
public static final String COPY = "copy";
- 在 copyImagesToTempFolder 方法内部,递增一个计数器变量,然后通过调用它的
firePropertyChange
方法通知所有注册了您的 SwingPropertyChangeSupport 实例的侦听器。 Bound Properties Tutorial 可以帮助您了解细节。
- 让您的 MainWindow class 通过调用其
addPropertyChangeListener(...)
方法并传入有效的 PropertyChangeListener 来为其 CopyService 实例注册一个侦听器(再次检查上面链接的教程)。
- 在此 属性 更改侦听器中,获取状态更改信息并使用它来更新 JProgressBar。
- 重要,在后台线程中调用
copyImagesToTempFolder(...)
方法——为此使用 SwingWorker,本教程将帮助您:Lesson: Concurrency in Swing。如果您不使用后台线程,那么文件更改过程将阻塞 Swing 事件线程,有效地冻结您的 GUI 并阻止您的进度条前进。
另一个可能更好的选择是让您的 CopyService class 扩展 SwingWorker,然后使用已经连接到 SwingWorker 中的相同侦听器机制来实现您的目标。
例如:
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
@SuppressWarnings("serial")
public class ProgressMcve extends JPanel {
private JProgressBar progressBar = new JProgressBar(0, 100);
private CopyAction copyAction = new CopyAction();
public ProgressMcve() {
progressBar.setStringPainted(true);
add(progressBar);
add(new JButton(copyAction));
}
private class CopyAction extends AbstractAction {
public CopyAction() {
super("Copy");
putValue(MNEMONIC_KEY, KeyEvent.VK_C);
}
@Override
public void actionPerformed(ActionEvent e) {
setEnabled(false);
progressBar.setValue(0);
MockCopyService copyService = new MockCopyService();
copyService.addPropertyChangeListener(new CopyServiceListener());
copyService.execute();
}
}
private class CopyServiceListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
int progress = (int) evt.getNewValue();
progressBar.setValue(progress);
} else if (SwingWorker.StateValue.DONE == evt.getNewValue()) {
progressBar.setValue(100);
progressBar.setString("Done");
copyAction.setEnabled(true);
try {
((MockCopyService) evt.getSource()).get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
}
private static void createAndShowGui() {
ProgressMcve mainPanel = new ProgressMcve();
JFrame frame = new JFrame("ProgressMcve");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
// simple MCVE example class that mocks the functioning of your class
public class MockCopyService extends SwingWorker<Void, Integer> {
public static final String COPY = "copy";
private List<File> fileList = new ArrayList<>();
public MockCopyService() {
}
public int getFileListSize() {
// the real return:
// return fileList.size();
// the mock return:
return 10;
}
public void copyImagesToTempFolder() {
for (int i = 0; i < getFileListSize(); i++) {
System.out.println("copying file");
int fileProgress = (100 * i) / getFileListSize();
// notify listeners
setProgress(fileProgress);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
setProgress(getFileListSize());
}
@Override
protected Void doInBackground() throws Exception {
copyImagesToTempFolder();
return null;
}
}
我有一个 class 从一个文件夹列表中执行复制的文件,这些文件首先作为 .txt 加载,然后复制到临时文件夹。我想显示将文件复制到文件夹的进度,反之亦然
这是我的副本class:
public class CopyService {
private String _destLocation;
private List<File> _filePaths = new ArrayList<File>();
private Map<String, String> _fileProperties = new HashMap<String, String>();
private String _rootLocation;
private File _txtFile;
public CopyService() {
setRootLocation(NekretnineService.getRootFolder());
setDestLocation(NekretnineService.getDestFolder());
}
public void copyImagesToTempFolder() throws IOException {
File destLocationFolder = new File(getDestLocation());
if (getFilePaths() != null) {
if (!destLocationFolder.exists()) {
destLocationFolder.mkdir();
}
for (File f : getFilePaths()) {
if (f.exists()) {
FileUtils.copyFileToDirectory(f, destLocationFolder);
}
}
}
}
public String getDestLocation() {
return _destLocation;
}
public List<File> getFilePaths() {
return _filePaths;
}
public Map<String, String> getFileProperties() {
return _fileProperties;
}
public String getRootLocation() {
return _rootLocation;
}
public File getTxtFile() {
return _txtFile;
}
public void loadTxtFile(File txtFile) throws Exception {
try {
int lines = 0;
List<String> imgNames = new ArrayList<String>();
try (BufferedReader br = new BufferedReader(new FileReader(txtFile))) {
String txtLine;
while ((txtLine = br.readLine()) != null) {
imgNames.add(txtLine);
lines++;
}
}
for (String img : imgNames) {
String fullPath = getRootLocation();
fullPath += File.separator + img;
getFilePaths().add(new File(fullPath));
fullPath = "";
}
_fileProperties.put("filename", txtFile.getName());
_fileProperties.put("filesize", String.valueOf(txtFile.length()));
_fileProperties.put("totalimgs", String.valueOf(lines));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public void setDestLocation(String destLocation) {
_destLocation = destLocation;
}
public void setFilePaths(List<File> filePaths) {
_filePaths = filePaths;
}
public void setFileProperties(Map<String, String> fileProperties) {
_fileProperties = fileProperties;
}
public void setRootLocation(String rootLocation) {
_rootLocation = rootLocation;
}
public void setTxtFile(File txtFile) {
_txtFile = txtFile;
}
@Override
public String toString() {
return "CopyService [_destLocation=" + _destLocation + ", _filePaths=" + _filePaths + ", _fileProperties="
+ _fileProperties + ", _rootLocation=" + _rootLocation + ", _txtFile=" + _txtFile + "]";
}
}
这是我的 GUI window 使用 window 构建器制作的:
public class MainWindow extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel _contentPane;
private CopyService copyService;
private JLabel lblFileName;
private JLabel lblFileSize;
private JLabel lblImagesCount;
private JTextField txtImgDestination;
private JTextField txtRootLocation;
public MainWindow() {
Image img = new ImageIcon(getClass().getClassLoader().getResource("ico_house.png")).getImage();
setIconImage(img);
setSize(450, 341);
setTitle("Nekretnine Service");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
setLocationRelativeTo(null);
_contentPane = new JPanel();
_contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(_contentPane);
_contentPane.setLayout(null);
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
tabbedPane.setBounds(0, 0, 434, 261);
_contentPane.add(tabbedPane);
JPanel backupTab = new JPanel();
tabbedPane.addTab("Backup", null, backupTab, null);
JPanel imgCleanerTab = new JPanel();
tabbedPane.addTab("Image Cleaner", null, imgCleanerTab, null);
imgCleanerTab.setLayout(null);
JPanel panel = new JPanel();
panel.setBorder(new BevelBorder(BevelBorder.LOWERED, Color.BLACK, null, null, null));
panel.setBounds(10, 11, 409, 73);
imgCleanerTab.add(panel);
panel.setLayout(null);
lblFileName = new JLabel("Filename:");
lblFileName.setBounds(20, 11, 247, 14);
panel.add(lblFileName);
lblFileName.setFont(new Font("Tahoma", Font.BOLD, 11));
lblFileSize = new JLabel("Size:");
lblFileSize.setBounds(20, 30, 247, 14);
panel.add(lblFileSize);
lblFileSize.setFont(new Font("Tahoma", Font.BOLD, 11));
lblImagesCount = new JLabel("Total images to copy:");
lblImagesCount.setBounds(20, 49, 247, 14);
panel.add(lblImagesCount);
lblImagesCount.setFont(new Font("Tahoma", Font.BOLD, 11));
JButton btnCopyBack = new JButton("Copy to location");
btnCopyBack.setEnabled(false);
btnCopyBack.setFont(new Font("Tahoma", Font.PLAIN, 12));
btnCopyBack.setBounds(10, 165, 200, 23);
imgCleanerTab.add(btnCopyBack);
JButton btnDelete = new JButton("Clean images folder");
btnDelete.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
btnCopyBack.setEnabled(true);
}
});
btnDelete.setEnabled(false);
btnDelete.setFont(new Font("Tahoma", Font.PLAIN, 12));
btnDelete.setBounds(10, 131, 200, 23);
imgCleanerTab.add(btnDelete);
JButton btnCopyImagesToTemp = new JButton("Copy images to temp folder");
btnCopyImagesToTemp.setEnabled(false);
btnCopyImagesToTemp.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
copyService.copyImagesToTempFolder();
btnDelete.setEnabled(true);
} catch (IOException e1) {
JOptionPane.showMessageDialog(_contentPane, "File error " + e1.getMessage(), "Error",
JOptionPane.ERROR_MESSAGE);
}
}
});
btnCopyImagesToTemp.setFont(new Font("Tahoma", Font.PLAIN, 12));
btnCopyImagesToTemp.setBounds(10, 97, 200, 23);
imgCleanerTab.add(btnCopyImagesToTemp);
JButton btnFileList = new JButton("Images List");
btnFileList.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new FileList(copyService.getFilePaths()).setVisible(true);
}
});
btnFileList.setEnabled(false);
btnFileList.setBounds(276, 7, 123, 23);
panel.add(btnFileList);
JButton btnLoadTxtFile = new JButton("Load .txt File");
btnLoadTxtFile.addActionListener(new ActionListener() {
@SuppressWarnings("static-access")
public void actionPerformed(ActionEvent e) {
try {
JFileChooser jf = new JFileChooser("C:\");
FileNameExtensionFilter filter = new FileNameExtensionFilter("TEXT FILES", "txt", "text");
jf.setFileFilter(filter);
int status = jf.showOpenDialog(_contentPane);
if (status == jf.APPROVE_OPTION) {
copyService = new CopyService();
copyService.loadTxtFile(jf.getSelectedFile());
lblFileName.setText("Filename:" + " " + copyService.getFileProperties().get("filename"));
lblFileSize.setText("Size:" + " " + copyService.getFileProperties().get("filesize") + " b");
lblImagesCount.setText(
"Total images to copy:" + " " + copyService.getFileProperties().get("totalimgs"));
btnFileList.setEnabled(true);
btnCopyImagesToTemp.setEnabled(true);
} else {
JOptionPane.showMessageDialog(_contentPane, "Error while choosing file", "Error",
JOptionPane.ERROR_MESSAGE);
}
} catch (Exception e1) {
JOptionPane.showMessageDialog(_contentPane, "File error " + e1.getMessage(), "Error",
JOptionPane.ERROR_MESSAGE);
}
}
});
btnLoadTxtFile.setBounds(277, 45, 123, 23);
panel.add(btnLoadTxtFile);
JProgressBar progressBar = new JProgressBar();
progressBar.setBounds(10, 199, 409, 23);
imgCleanerTab.add(progressBar);
JPanel confifgTab = new JPanel();
tabbedPane.addTab("Settings", null, confifgTab, null);
confifgTab.setLayout(null);
JButton btnSaveSettings = new JButton("Save Settings");
btnSaveSettings.setFont(new Font("Tahoma", Font.BOLD, 12));
btnSaveSettings.setBounds(294, 202, 125, 20);
confifgTab.add(btnSaveSettings);
txtRootLocation = new JTextField();
txtRootLocation.setEditable(false);
txtRootLocation.setBounds(10, 34, 259, 20);
confifgTab.add(txtRootLocation);
txtRootLocation.setColumns(10);
JLabel lblNewLabel = new JLabel("Root folder for images:");
lblNewLabel.setBounds(10, 11, 140, 14);
confifgTab.add(lblNewLabel);
JButton btnSelectRootFolder = new JButton("Select Folder");
btnSelectRootFolder.setBounds(279, 33, 140, 23);
confifgTab.add(btnSelectRootFolder);
txtImgDestination = new JTextField();
txtImgDestination.setEditable(false);
txtImgDestination.setColumns(10);
txtImgDestination.setBounds(10, 88, 259, 20);
confifgTab.add(txtImgDestination);
JLabel lblDestinationFolderFor = new JLabel("Destination folder for images:");
lblDestinationFolderFor.setBounds(10, 65, 259, 14);
confifgTab.add(lblDestinationFolderFor);
JButton btnSelectDestFolder = new JButton("Select Folder");
btnSelectDestFolder.setBounds(279, 87, 140, 23);
confifgTab.add(btnSelectDestFolder);
}
public JTextField getTxtImgDestination() {
return txtImgDestination;
}
public JTextField getTxtRootLocation() {
return txtRootLocation;
}}
想在进度条上显示复制进度,不知道怎么实现,只知道while复制方法和gui一样class
您将希望允许外部 classes 在复制文件时监听 CopyService class 状态的变化,但幸运的是 Java 和 Swing 具有用于这个,但是你需要付出一些努力来学习如何使用这些库。建议:
- 给CopyServiceclass一个SwingPropertyChangeSupport私有实例字段,初始化实例,传入
this
,当前class。该对象具有允许其接受侦听器的机制,然后您作为编码人员可以通过调用其方法将 class 中的状态更改通知这些侦听器。 - 为 class 提供一个
public void addPropertyChangeListener(PropertyChangeListener l)
委托方法,并在该方法内将侦听器添加到 SwingPropertyChangeSupport 实例。 - 给class一个public常量字符串,比如
public static final String COPY = "copy";
- 在 copyImagesToTempFolder 方法内部,递增一个计数器变量,然后通过调用它的
firePropertyChange
方法通知所有注册了您的 SwingPropertyChangeSupport 实例的侦听器。 Bound Properties Tutorial 可以帮助您了解细节。 - 让您的 MainWindow class 通过调用其
addPropertyChangeListener(...)
方法并传入有效的 PropertyChangeListener 来为其 CopyService 实例注册一个侦听器(再次检查上面链接的教程)。 - 在此 属性 更改侦听器中,获取状态更改信息并使用它来更新 JProgressBar。
- 重要,在后台线程中调用
copyImagesToTempFolder(...)
方法——为此使用 SwingWorker,本教程将帮助您:Lesson: Concurrency in Swing。如果您不使用后台线程,那么文件更改过程将阻塞 Swing 事件线程,有效地冻结您的 GUI 并阻止您的进度条前进。
另一个可能更好的选择是让您的 CopyService class 扩展 SwingWorker,然后使用已经连接到 SwingWorker 中的相同侦听器机制来实现您的目标。
例如:
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
@SuppressWarnings("serial")
public class ProgressMcve extends JPanel {
private JProgressBar progressBar = new JProgressBar(0, 100);
private CopyAction copyAction = new CopyAction();
public ProgressMcve() {
progressBar.setStringPainted(true);
add(progressBar);
add(new JButton(copyAction));
}
private class CopyAction extends AbstractAction {
public CopyAction() {
super("Copy");
putValue(MNEMONIC_KEY, KeyEvent.VK_C);
}
@Override
public void actionPerformed(ActionEvent e) {
setEnabled(false);
progressBar.setValue(0);
MockCopyService copyService = new MockCopyService();
copyService.addPropertyChangeListener(new CopyServiceListener());
copyService.execute();
}
}
private class CopyServiceListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
int progress = (int) evt.getNewValue();
progressBar.setValue(progress);
} else if (SwingWorker.StateValue.DONE == evt.getNewValue()) {
progressBar.setValue(100);
progressBar.setString("Done");
copyAction.setEnabled(true);
try {
((MockCopyService) evt.getSource()).get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
}
private static void createAndShowGui() {
ProgressMcve mainPanel = new ProgressMcve();
JFrame frame = new JFrame("ProgressMcve");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
// simple MCVE example class that mocks the functioning of your class
public class MockCopyService extends SwingWorker<Void, Integer> {
public static final String COPY = "copy";
private List<File> fileList = new ArrayList<>();
public MockCopyService() {
}
public int getFileListSize() {
// the real return:
// return fileList.size();
// the mock return:
return 10;
}
public void copyImagesToTempFolder() {
for (int i = 0; i < getFileListSize(); i++) {
System.out.println("copying file");
int fileProgress = (100 * i) / getFileListSize();
// notify listeners
setProgress(fileProgress);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
setProgress(getFileListSize());
}
@Override
protected Void doInBackground() throws Exception {
copyImagesToTempFolder();
return null;
}
}