agregar barra de progreso a cada celda de la tabla para el progreso del archivo – Java

La aplicación cifra cada archivo que se coloca en la tabla cuando se hace clic en encriptar y me gustaría mostrar el progreso de los archivos a medida que se encriptan. La columna “Estado” cambiará de “No procesada” a “Procesada”.

Similar a la forma en que mira archivos múltiples adjuntar en un correo electrónico. He estado buscando en el procesador de células y en el ProgressBarTablecell, pero no estoy seguro de cómo implementarlos. Cualquier ayuda apreciada. Estoy publicando la tabla.

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(); 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); } } } 

Aquí hay un ejemplo básico, esto básicamente usa un SwingWorker para escanear el directorio raíz de su disco y enumera todos los archivos. Una vez que se haya completado, intentará leer cada archivo, en su propio SwingWorker actualizando la tabla a medida que avanza.

Descargo de responsabilidad: este es un ejemplo. Uso un Thread.sleep para ralentizar las lecturas ligeramente, ignoro los buffers y algunas otras cosas, lo haría de forma diferente en el código de producción, pero quería resaltar las actualizaciones de progreso.

enter image description here

Cómo funciona

En primer lugar, necesita un procesador de células capaz de mostrar actualizaciones de progreso. JProgressBar una JProgressBar personalizada simple, pero es posible que te guste algo un poco más sofisticado.

Necesita alguna forma de actualizar el modelo de tabla. Elegí proporcionar un método simple updateStatus , pasando el archivo que estoy actualizando, esto me permite usar búsquedas internas para encontrar la fila en cuestión. Luego uso el método setValueAt para actualizar el objeto de la fila. Esto no es realmente necesario, pero quería demostrar el uso del método setValueAt , podría haber actualizado el objeto fila directamente desde el método updateStatus .

Y finalmente, notifique a la tabla de cambios al modelo para que se vuelva a pintar.

 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 rows; private Map 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, File> { private UpdatableTableModel model; public FileFinderWorker(UpdatableTableModel model) { this.model = model; } @Override protected void process(List chunks) { for (File file : chunks) { model.addFile(file); } } @Override protected List doInBackground() throws Exception { File files[] = new File(System.getProperty("user.dir")).listFiles(); List 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 files = get(); for (File file : files) { new FileReaderWorker(model, file).execute(); } } catch (Exception exp) { exp.printStackTrace(); } } } public class FileReaderWorker extends SwingWorker { 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; } } } 

Conceptos importantes

NUNCA, NUNCA bloquee el hilo de distribución de eventos con ningún tipo de operación de larga ejecución. En cambio, mueva estas operaciones que consumen mucho tiempo a una cadena de fondo. Aquí, he usado SwingWorker

Haga una lectura simultánea en Swing para obtener más información

Necesitará un TableCellRenderer que contenga una JProgressBar , como se muestra aquí . Puede actualizar el progreso de cada archivo desde un SwingWorker , que se ve aquí .

imagen

Necesita tener algún tipo de proceso con un valor entero entre 0 y 100. Por ejemplo:

 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; } 

Esto se modela en las tablas tableModel.

Se necesita un procesador para devolver una barra de progreso en una de las columnas de las tablas:

 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; } } 

Ahora solo necesita un hilo para hacer algo en segundo plano y actualizar los objetos de proceso. El ejemplo completo, del cual he copiado fragmentos de código, se puede encontrar aquí .

enter image description here