当您单击加密时,应用程序会加密放入表中的每个文件,并且我希望显示文件在加密时的进度。然后,“状态”列将从“未处理”更改为“已处理”。
与您在电子邮件中观看多个文件的方式类似。我一直在研究单元格渲染器和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);
}
}
}
答案 0 :(得分:25)
这是一个基本示例,它基本上使用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 :(得分:7)
答案 2 :(得分:0)
您需要使用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;
}
}
现在您只需要一个线程在后台执行某些操作并更新过程对象。我已经复制了代码片段的完整示例here。