Как я могу показать индикатор выполнения с помощью Swingworker? - PullRequest
0 голосов
/ 28 января 2020

Это мой фрагмент кода. При нажатии на кнопку он выполняет загрузку программы в фоновом режиме, но я не могу получить подробную информацию о задаче в индикатор выполнения. Может кто-нибудь сказать мне, что мне здесь не хватает?

Дело в том, что я не хочу включать весь код вставки в мой метод doInBackground.

public class ProgressBarDemo extends JPanel
                             implements ActionListener, 
                                        PropertyChangeListener {
private JProgressBar progressBar;
private JButton startButton;
private JTextArea taskOutput;
private Task task;

class Task extends SwingWorker<Void, Integer> {
    @Override
    protected void process(List<Integer> arg0) {
        // TODO Auto-generated method stub
        super.process(arg0);
        for(int k:arg0)
        System.out.println("arg is "+k);
        setProgress(arg0.size()-1);
    }

    /*
     * Main task. Executed in background thread.
     */
    @Override
    public Void doInBackground() throws Exception {
        Random random = new Random();
        int progress = 0;
        //Initialize progress property.
        setProgress(0);
        Thread.sleep(100);
        new LoadUnderwritingData().filesinfolder("D:\\files to upload\\");
        System.out.println("records inserted are "+LoadData.records_count_inserted);
        publish(LoadData.records_count_inserted);
        /*
         * while (progress < 100) { //Sleep for up to one second. try {
         * Thread.sleep(random.nextInt(1000)); } catch (InterruptedException ignore) {}
         * //Make random progress. progress += random.nextInt(10);
         * setProgress(Math.min(progress, 100)); }
         */
        return null;
    }

    /*
     * Executed in event dispatching thread
     */
    @Override
    public void done() {
        Toolkit.getDefaultToolkit().beep();
        startButton.setEnabled(true);
        setCursor(null); //turn off the wait cursor
        taskOutput.append("Done!\n");
    }
}

1 Ответ

0 голосов
/ 29 января 2020

Я вижу, вы не звоните progressBar.setValue(progress);. Также вам нужно будет вызывать publish(currentInsertCount); после каждого вставленного элемента. В методе процесса вы должны сделать:

// assuming you are passing the current insert count to publish()
for (int k : arg0){
    System.out.println("arg is " + k);
    progressBar.setValue(k);
}

Однако из того, что вы опубликовали сейчас, не совсем понятно, где вообще происходит обработка. Это эта строка:

new LoadUnderwritingData().filesinfolder("D:\\files to upload\\");

Если это так, вам придется передать некоторый Callback на filesinfolder("..."), чтобы он мог обновлять ход выполнения.

Примечание: может быть проще сделать это в простом новом потоке вместо использования SwingWorker.

Как я бы сделал это с простым потоком:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileFilter;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class ProgressBarDemo extends JPanel implements ActionListener {

    private JProgressBar progressBar;
    private JButton startButton;
    private JTextArea taskOutput;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("ProgressBarDemo");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().setPreferredSize(new Dimension(500, 500));
            frame.add(new ProgressBarDemo());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }

    public ProgressBarDemo() {
        progressBar = new JProgressBar(0, 100);
        startButton = new JButton(">");
        taskOutput = new JTextArea();

        startButton.addActionListener(this);

        setLayout(new BorderLayout());
        add(startButton, BorderLayout.NORTH);
        add(taskOutput, BorderLayout.CENTER);
        add(progressBar, BorderLayout.SOUTH);

        progressBar.setVisible(false);
    }

    // If you don't care about a small chance of the UI not updating properly then you can perform the updates directly instead of calling invokeLater.
    // If you are compiling below Java 1.8, you need to convert Lambda expression to a Runnable and make the directory parameter final.
    public void upload(File directory) {
        // No need for invokeLater here because this is called within the AWT Event Handling
        startButton.setEnabled(false);
        progressBar.setVisible(true);
        new Thread() {

            @Override
            public void run() {
                taskOutput.append("Discovering files...\n");
                // List<File> files = Arrays.asList(directory.listFiles()); //
                // if you want to process both files and directories, but only
                // in the given folder, not in any sub folders
                // List<File> files = Arrays.asList(getAllFiles(directory)); //
                // if you only want the files in that directory, but not in sub
                // directories
                List<File> files = getAllFilesRecursive(directory); // if you
                                                                    // want all
                                                                    // files

                SwingUtilities.invokeLater(() -> {
                    taskOutput.append("  -> discovered " + files.size() + " files.\n");
                    progressBar.setMaximum(files.size());
                    taskOutput.append("Processing files...\n");
                });
                int processedCount = 0;
                for (File file : files) {
                    try {
                        byte[] bytes = Files.readAllBytes(file.toPath());
                        // TODO: process / upload or whatever you want to do with it
                    } catch (Throwable e) {
                        // Same here, you may skip the invokeLater
                        SwingUtilities.invokeLater(() -> taskOutput.append("Failed to process " + file.getName() + ": " + e.getMessage() + "\n"));
                        e.printStackTrace();
                    } finally {
                        processedCount++;
                        final int prcCont = processedCount; // not necessary if invoking directly
                        SwingUtilities.invokeLater(() -> progressBar.setValue(prcCont));
                    }
                }
                SwingUtilities.invokeLater(() -> {
                    taskOutput.append("  -> done.\n");
                    startButton.setEnabled(true);
                    progressBar.setVisible(false);
                });
            }
        }.start();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        upload(new File("C:\\directoryToUpload"));
    }

    /**
     * Gets all normal files in the directory.
     */
    public static File[] getAllFiles(File directory) {
        return directory.listFiles(new FileFilter() {

            @Override
            public boolean accept(File pathname) {
                return pathname.isFile();
            }
        });
    }

    /**
     * Gets all normal files in the given directory and its sub directories.
     */
    public static List<File> getAllFilesRecursive(File directory) {
        List<File> result = new ArrayList<File>();
        getAllFilesRecursive(directory, result);
        return result;

    }

    private static void getAllFilesRecursive(File directory, List<File> addTo) {
        if (directory.isFile()) {
            addTo.add(directory);
        } else if (directory.isDirectory()) {
            File[] subFiles = directory.listFiles();
            if (subFiles == null)
                return;
            for (File subFile : subFiles) {
                getAllFilesRecursive(subFile, addTo);
            }
        }
    }

}
...