Добавление индикатора выполнения для каждой ячейки таблицы для прогресса файла - Java

Приложение шифрует каждый файл, который помещается в таблицу, когда вы щелкаете зашифровать, и я хотел бы показать прогресс файлов по мере их шифрования. Затем столбец "Статус" изменится с "Не обработан" на "Обработан".

Аналогично тому, как вы просматриваете несколько файлов, прикрепленных в электронном письме. Я просматривал рендеринг ячеек и ProgressBarTablecell, но не знаю, как их реализовать. Любая помощь оценивается. Я отправляю стол.

        import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Point;
    import java.awt.datatransfer.DataFlavor;
    import java.awt.datatransfer.Transferable;
    import java.awt.datatransfer.UnsupportedFlavorException;
    import java.awt.dnd.DnDConstants;
    import java.awt.dnd.DropTarget;
    import java.awt.dnd.DropTargetDragEvent;
    import java.awt.dnd.DropTargetDropEvent;
    import java.io.File;
    import java.io.IOException;
    import java.util.List;

    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    import javax.swing.table.DefaultTableModel;

    public class DropTable {

        public static void main(String[] args) {
            new DropTable();
        }

        public DropTable() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager
                                .getSystemLookAndFeelClassName());//get look and feel of whatever OS we're using
                    } catch (ClassNotFoundException | InstantiationException
                            | IllegalAccessException
                            | UnsupportedLookAndFeelException ex) {
                    }

                    JFrame frame = new JFrame();
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new DropPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }

            });
        }

        public class DropPane extends JPanel {

            /**
             * 
             */
            private static final long serialVersionUID = 1L;
            private JTable table;
            private JScrollPane scroll;
            private DefaultTableModel tm = new DefaultTableModel(new String[] {
                    "File", "File Type", "Size", "Status" }, 0);

            public DropPane() {
                table = new JTable();
                table.setShowGrid(true);
                table.setShowHorizontalLines(true);
                table.setShowVerticalLines(true);
                table.setGridColor(Color.GRAY);


                table.setModel(tm);
                table.setFillsViewportHeight(true);
                table.setPreferredSize(new Dimension(500, 300));

                scroll = new JScrollPane(table);

                table.setDropTarget(new DropTarget() {
                    @Override
                    public synchronized void dragOver(DropTargetDragEvent dtde) {
                        Point point = dtde.getLocation();
                        int row = table.rowAtPoint(point);
                        if (row < 0) {
                            table.clearSelection();
                        } else {
                            table.setRowSelectionInterval(row, row);
                        }
                        dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
                    }

                    @Override
                    public synchronized void drop(DropTargetDropEvent dtde) {
                        if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
                        {//make sure the flavors are files
                            dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);//dndconstants tells what to do with the drag files
                            //change to ACTION_COPY so it removes the file from the directory
                            Transferable t = dtde.getTransferable();
                            List fileList = null;
                            try {
                                fileList = (List) t.getTransferData(DataFlavor.javaFileListFlavor);//get file
                                if (fileList.size() > 0) {
                                    table.clearSelection();
                                    Point point = dtde.getLocation();//point is (x,y) 
                                    int row = table.rowAtPoint(point);
                                    DefaultTableModel model = (DefaultTableModel) table.getModel();
                                    for (Object value : fileList) {
                                        if (value instanceof File) {
                                            File f = (File) value;

                                            if (row < 0) {//insert rows into the right columns
                                            model.addRow(new Object[]{f.getAbsolutePath(), "", f.length(), "", ""});//path under "File"
                                            } else {
                                                model.insertRow(row, new Object[]{f.getAbsolutePath(), "", f.length(), "", ""});//get size of file
                                                row++;

                                            }
                                        }
                                    }
                                }
                            } catch (UnsupportedFlavorException e) {
                                e.printStackTrace();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        } else {
                            dtde.rejectDrop();
                        }
                    }

                });

                add(scroll, BorderLayout.CENTER);
            }
        }
    }

Ответ 1

Вот базовый пример: в основном это использует SwingWorker для сканирования корневого каталога вашего диска и перечисления всех файлов. Как только это будет завершено, он попытается прочитать каждый файл, в нем собственный SwingWorker обновляющий таблицу по мере ее появления.

Отказ от ответственности: Это пример. Я использую Thread.sleep чтобы Thread.sleep замедлить чтение, игнорировать буферы и несколько других вещей, которые я делал бы по-другому в производственном коде, но я хотел бы выделить обновления прогресса.

enter image description here

Как это работает

Во-первых, вам понадобится средство отображения ячеек, способное отображать обновления хода. Я выбрал простой пользовательский JProgressBar, но вам может понравиться что-то более сложное.

Вам нужно каким-то образом обновить модель таблицы. Я решил предоставить простой метод updateStatus, передав файл, который я обновляю, это позволяет мне использовать внутренние updateStatus, чтобы найти строку, о которой идет речь. Затем я использую метод setValueAt для обновления объекта строки. Это действительно не требуется, но я хотел продемонстрировать использование метода setValueAt, вы могли бы напрямую обновить объект строки из метода updateStatus.

И, наконец, сообщите таблицу изменений модели, чтобы она перекрашивалась сама.

public class UpdateTable {

    public static void main(String[] args) {
        new UpdateTable();
    }

    public UpdateTable() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                UpdatableTableModel model = new UpdatableTableModel();

                JTable table = new JTable();
                table.setModel(model);

                table.getColumn("Status").setCellRenderer(new ProgressCellRender());

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                FileFinderWorker worker = new FileFinderWorker(model);
                worker.execute();

            }
        });
    }

    public class ProgressCellRender extends JProgressBar implements TableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            int progress = 0;
            if (value instanceof Float) {
                progress = Math.round(((Float) value) * 100f);
            } else if (value instanceof Integer) {
                progress = (int) value;
            }
            setValue(progress);
            return this;
        }
    }

    public class RowData {

        private File file;
        private String type;
        private long length;
        private float status;

        public RowData(File file, String type) {
            this.file = file;
            this.type = type;
            this.length = file.length();
            this.status = 0f;
        }

        public File getFile() {
            return file;
        }

        public long getLength() {
            return length;
        }

        public float getStatus() {
            return status;
        }

        public String getType() {
            return type;
        }

        public void setStatus(float status) {
            this.status = status;
        }
    }

    public class UpdatableTableModel extends AbstractTableModel {

        private List<RowData> rows;
        private Map<File, RowData> mapLookup;

        public UpdatableTableModel() {
            rows = new ArrayList<>(25);
            mapLookup = new HashMap<>(25);
        }

        @Override
        public int getRowCount() {
            return rows.size();
        }

        @Override
        public int getColumnCount() {
            return 4;
        }

        @Override
        public String getColumnName(int column) {
            String name = "??";
            switch (column) {
                case 0:
                    name = "File";
                    break;
                case 1:
                    name = "File Type";
                    break;
                case 2:
                    name = "Size";
                    break;
                case 3:
                    name = "Status";
                    break;
            }
            return name;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            RowData rowData = rows.get(rowIndex);
            Object value = null;
            switch (columnIndex) {
                case 0:
                    value = rowData.getFile();
                    break;
                case 1:
                    value = rowData.getType();
                    break;
                case 2:
                    value = rowData.getLength();
                    break;
                case 3:
                    value = rowData.getStatus();
                    break;
            }
            return value;
        }

        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            RowData rowData = rows.get(rowIndex);
            switch (columnIndex) {
                case 3:
                    if (aValue instanceof Float) {
                        rowData.setStatus((float) aValue);
                    }
                    break;
            }
        }

        public void addFile(File file) {
            RowData rowData = new RowData(file, "A File");
            mapLookup.put(file, rowData);
            rows.add(rowData);
            fireTableRowsInserted(rows.size() - 1, rows.size() - 1);
        }

        protected void updateStatus(File file, int progress) {
            RowData rowData = mapLookup.get(file);
            if (rowData != null) {
                int row = rows.indexOf(rowData);
                float p = (float) progress / 100f;
                setValueAt(p, row, 3);
                fireTableCellUpdated(row, 3);
            }
        }
    }

    public class FileFinderWorker extends SwingWorker<List<File>, File> {

        private UpdatableTableModel model;

        public FileFinderWorker(UpdatableTableModel model) {
            this.model = model;
        }

        @Override
        protected void process(List<File> chunks) {
            for (File file : chunks) {
                model.addFile(file);
            }
        }

        @Override
        protected List<File> doInBackground() throws Exception {
            File files[] = new File(System.getProperty("user.dir")).listFiles();
            List<File> lstFiles = new ArrayList<>(Arrays.asList(files));
            for (File file : lstFiles) {
                // You could actually publish the entire array, but I'm doing this
                // deliberatly ;)
                publish(file);
            }
            return lstFiles;
        }

        @Override
        protected void done() {
            try {
                List<File> files = get();
                for (File file : files) {
                    new FileReaderWorker(model, file).execute();
                }
            } catch (Exception exp) {
                exp.printStackTrace();
            }
        }
    }

    public class FileReaderWorker extends SwingWorker<File, File> {

        private File currentFile;
        private UpdatableTableModel model;

        public FileReaderWorker(UpdatableTableModel model, File file) {
            this.currentFile = file;
            this.model = model;

            addPropertyChangeListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    if (evt.getPropertyName().equals("progress")) {
                        FileReaderWorker.this.model.updateStatus(currentFile, (int) evt.getNewValue());
                    }
                }
            });

        }

        @Override
        protected File doInBackground() throws Exception {
            if (currentFile.isFile()) {
                setProgress(0);
                long fileLength = currentFile.length();
                BufferedReader reader = null;
                char[] cbuf = new char[1024];
                try {
                    reader = new BufferedReader(new FileReader(currentFile));
                    int bytesRead = -1;
                    int totalBytesRead = 0;
                    while ((bytesRead = reader.read(cbuf)) != -1) {
                        totalBytesRead += bytesRead;
                        int progress = (int) Math.round(((double) totalBytesRead / (double) fileLength) * 100d);
                        setProgress(progress);
                        Thread.sleep(25);
                    }
                    setProgress(100);
                } catch (Exception e) {
                    e.printStackTrace();
                    setProgress(100);
                } finally {
                    try {
                        reader.close();
                    } catch (Exception e) {
                    }
                }
            } else {
                setProgress(100);
            }
            return currentFile;
        }
    }
}

Важные понятия.

НИКОГДА, НИКОГДА не блокируйте Thread Dispatching Thread с любой продолжительной работой. Вместо этого переместите эти трудоемкие операции в фоновый поток. Здесь я использовал SwingWorker

Прочитайте параллелизм в Swing для получения дополнительной информации.

Ответ 2

Вам понадобится TableCellRenderer, который содержит JProgressBar, как показано здесь. Вы можете обновить каждый файл с SwingWorker, увиденный здесь.

image

Ответ 3

У вас должен быть какой-то процесс с целым значением от 0 до 100. Например:

class Process {

    public Process(String name, int progress, String description) {
        super();
        this.name = name;
        this.progress = progress;
        this.description = description;
    }

    String name;
    int progress;
    String description; }

Это моделируется в таблице tableModel.

Для возврата индикатора выполнения в один из столбцов таблиц необходим рендерер:

class ProgressRenderer extends DefaultTableCellRenderer {
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row2, int column) {

        int row = table.convertRowIndexToModel(row2);

        ProcessTableModel mtm = (ProcessTableModel) table.getModel();
        Process p = (Process) mtm.getProcessAt(row);

        JProgressBar bar = new JProgressBar();
        bar.setValue(p.progress);
        return bar;
    }
}

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

enter image description here