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 在复制文件时监听 Co​​pyService 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;
    }
}