【问题标题】:adding progress bar to each table cell for file progress - Java为每个表格单元格添加进度条以获取文件进度 - Java
【发布时间】:2012-11-25 01:39:34
【问题描述】:

当您单击加密时,应用程序会加密放入表中的每个文件,并且我想在文件被加密时显示文件的进度。 “状态”列将从“未处理”变为“已处理”。

类似于查看电子邮件中附加的多个文件的方式。我一直在研究单元格渲染器和 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);
            }
        }
    }

【问题讨论】:

    标签: java swing file jtable jprogressbar


    【解决方案1】:

    这是一个基本示例,它基本上使用SwingWorker 扫描驱动器的根目录并列出所有文件。一旦完成,它将尝试读取每个文件,在它自己的SwingWorker 中更新表。

    免责声明:这是一个示例。我使用Thread.sleep 稍微减慢读取速度,忽略缓冲区和其他一些我会在生产代码中以不同方式执行的操作,但我想突出显示进度更新。

    工作原理

    首先,您需要一个能够显示进度更新的单元格渲染器。我选择了一个简单的自定义 JProgressBar,但您可能会喜欢更复杂的东西。

    您需要一些方法来更新表模型。我选择提供一个简单的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;
            }
        }
    }
    

    重要概念。

    永远不要用任何类型的长时间运行的操作阻塞事件调度线程。相反,将这些耗时的操作移到后台线程中。在这里,我使用了SwingWorker

    阅读Concurrency in Swing了解更多信息

    【讨论】:

    • +1 同时考虑System.getProperty("user.dir") over "C:/"。
    • @MadProgrammer 非常感谢您提供的示例。期待运行它,但是当我尝试运行它时,我在此处收到“无法从对象转换为 int”错误:FileReaderWorker.this.model.updateStatus(currentFile, (int) evt.getNewValue()); 和此处为 rowData.setStatus((float) aValue);
    • @trashgod 一定有什么东西:P
    • @healix 您使用的是什么版本的 Java?
    • @healix 如果你在那里投 Object 等效(即(浮动)到(浮动))它应该工作
    【解决方案2】:

    你需要有某种进程,其整数值在 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;
        }
    }
    

    现在您只需要一个线程在后台执行某些操作并更新进程对象。完整的例子,我复制了sn-ps的代码,可以在here找到。

    【讨论】:

      【解决方案3】:

      您需要一个包含JProgressBarTableCellRenderer,如here 所示。您可以从SwingWorker 更新每个文件的进度,见here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-31
        • 1970-01-01
        • 1970-01-01
        • 2015-08-24
        • 1970-01-01
        • 1970-01-01
        • 2020-02-05
        • 1970-01-01
        相关资源
        最近更新 更多