当您点击加密时,应用程序会加密放入表中的每个文件,并且我想在显示加密文件时的进度. “状态”列将从“未处理”更改为“已处理”.
类似于您在电子邮件中附加多个文件的方式.我一直在研究细胞渲染器和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(),""});//get size of file row++; } } } } } catch (UnsupportedFlavorException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } else { dtde.rejectDrop(); } } }); add(scroll,BorderLayout.CENTER); } } }
解决方法
这是一个基本的例子,它基本上使用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; } } }
重要概念.
永远,EVER阻止任何长时间运行的事件调度线程.相反,将这些耗时的操作移动到后台线程中.在这里,我使用了SwingWorker
阅读Concurrency in Swing了解更多信息