首先我們定義了GridBagConstraints的子類GBC,只是爲了調用GridBagConstraints時代碼更美觀和整潔。GBC子類的實現摘自《Java 核心技術 卷1》第十二章Swing用戶界面組件。GBC.java代碼如下:
import java.awt.GridBagConstraints;
import java.awt.Insets;
public class GBC extends GridBagConstraints {
public GBC(int gridx,int gridy)
{
this.gridx= gridx;
this.gridy= gridy;
}
public GBC(int gridx,int gridy,int gridwidth,int gridheight)
{
this.gridx= gridx;
this.gridy= gridy;
this.gridwidth = gridwidth;
this.gridheight = gridheight;
}
public GBC setAnchor(int anchor)
{
this.anchor=anchor;
return this;
}
public GBC setFill(int fill)
{
this.fill=fill;
return this;
}
public GBC setWeight(double weightx, double weighty)
{
this.weightx = weightx;
this.weighty = weighty;
return this;
}
public GBC setInsets(int distance)
{
this.insets= new Insets(distance,distance,distance,distance);
return this;
}
public GBC setInsets(int top,int left,int bottom,int right)
{
this.insets= new Insets( top, left, bottom, right);
return this;
}
public GBC setIpad(int ipadx,int ipady)
{
this.ipadx = ipadx;
this.ipady = ipady;
return this;
}
}
之後是主要的業務邏輯,在這裏實現了組件的添加,文件的遍歷邏輯。MainFrame.java代碼如下:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
public class MainFrame extends JFrame {
private String[] columns= {"Path","Name","Size(kb)","ModifyDate"};
private Object[][] cell= {};
private DefaultTableModel model;
private JTable table;
private JLabel PathLabel;
private JLabel ExpandLabel;
private JTextField PathField;
private JTextField ExpandField;
private String expandname;
Lock tablelock;
public MainFrame()
{
setSize(1000,800);
setLayout(new GridBagLayout());
//表格的初始化開始
model = new DefaultTableModel(cell,columns)
{
public Class<?> getColumnclass(int c)
{
return cell.getClass();
}
public boolean isCellEditable(int row,int column)
{
return false;
}
};
table = new JTable(model);
//使用windows觀感開始
try
{
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
}
catch(Exception e)
{
}
//使用windows觀感結束
//表格的初始化結束
tablelock = new ReentrantLock();
//輸入框的初始化開始
PathLabel = new JLabel("文件路徑:");
ExpandLabel = new JLabel("擴展名:");
PathField= new JTextField();
ExpandField = new JTextField();
//輸入框的初始化結束
//初始化按鍵開始
JPanel buttonPanel = new JPanel();
JButton buttonLoad = new JButton("加載");
JButton buttonDel = new JButton("刪除");
buttonPanel.add(buttonLoad);
buttonPanel.add(buttonDel);
//加載文件
buttonLoad.addActionListener(event->
{
LoadFile();
});
//刪除文件
buttonDel.addActionListener(enent->
{
DeleteFile();
});
//初始化按鍵結束
//添加輸入框開始
add(PathLabel,new GBC(0,0).setAnchor(GBC.EAST));
add(PathField,new GBC(1,0).setFill(GBC.HORIZONTAL).setWeight(50, 0));
add(ExpandLabel,new GBC(2,0).setAnchor(GBC.EAST));
add(ExpandField,new GBC(3,0).setFill(GBC.HORIZONTAL).setWeight(25, 0));
//添加輸入框結束
add(new JScrollPane(table),new GBC(0,5,7,7).setWeight(100, 100).setFill(GridBagConstraints.BOTH));
add(buttonPanel,new GBC(0,12,7,7));
pack();
}
//從輸入的目錄加載文件
public void LoadFile()
{
//加載文件之前,應該先清空表格
int rowcount = model.getRowCount();
while(rowcount!=0)
{
model.removeRow(rowcount-1);
rowcount = model.getRowCount();
}
File file = new File(PathField.getText());
expandname =ExpandField.getText();
RealLoadFile(file);
}
public void RealLoadFile(File file) throws NullPointerException
{
File contents[] = file.listFiles();
if(contents != null)
{
for(File files:contents)
{
if(files.isDirectory())//每一個文件夾起一個線程
{
try
{
Runnable search=()->
{
RealLoadFile(files);
};
new Thread(search).start();
}
catch(NullPointerException e)
{
System.out.println("error"+files.getName());
}
}
else
{
String name = files.getName();
String path = files.getParent();
String size=String.valueOf(files.length()/1024);
SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = timeFormat.format(files.lastModified());
String row[] = {path,name,size,time};
tablelock.lock();
if((0==expandname.length())||(expandname.length()>0&&name.endsWith(expandname)))
{
model.addRow(row);
}
tablelock.unlock();
}
}
}
}
public void DeleteFile()
{
int row[] = table.getSelectedRows();
String message;
String name;
String path;
String fullpath;
File file;
int option;
if(row.length==1)
{
name = model.getValueAt(row[0],1).toString();//
path = model.getValueAt(row[0],0).toString();//
fullpath =path+"\\"+name;
message ="確認刪除文件:"+name+"?";
option =JOptionPane.showConfirmDialog(null, message, "確認刪除?",JOptionPane.YES_NO_OPTION);
switch(option)
{
case JOptionPane.YES_OPTION:
file = new File(fullpath);
file.delete();
model.removeRow(row[0]);
break;
default:
break;
}
}
if(row.length>1)
{
message="確認刪除這"+row.length+"個文件嗎?";
option =JOptionPane.showConfirmDialog(null, message, "確認刪除?",JOptionPane.YES_NO_OPTION);
switch(option)
{
case JOptionPane.YES_OPTION:
for(int i=row.length-1;i>=0;i--)
{
name = model.getValueAt(row[i],1).toString();//
path = model.getValueAt(row[i],0).toString();//
fullpath =path+"\\"+name;
file = new File(fullpath);
file.delete();
model.removeRow(row[i]);
}
break;
default:
break;
}
}
}
}
需要重點說明以下幾點
1. 使用windows觀感純屬於個人喜好
2.文件夾遍歷採用了遞歸的方法,如果是文件夾,就調用RealLoadFile函數繼續調用,如果是文件,則獲取文件信息,添加到表格裏。
3. 爲了加快遍歷的速度,遇到文件夾會新起一個線程
4.文件信息添加到表格使用了鎖,防止同時給同一行添加數據(讀者可以把加鎖解鎖的地方去掉,多運行幾次,看看會出什麼錯誤)
5.遍歷文件時處理了異常,其實主要的異常時每個磁盤的根目錄下都有幾個猥瑣的操作系統隱藏文件夾無法處理。
6.刪除多個文件時按照表格的行號從大到小刪除,是因爲表格的行號其實是動態變化的,假如你刪除4,5,6,三行,刪除了第4行以後,第5行變成了第4行,因此你接下來刪除第5行其實是初始的第6行,刪除的第6行其實是初始的第7行.從後往前刪除就不存在這個問題
import java.awt.EventQueue;
import javax.swing.JFrame;
public class Client {
public static void main(String[] args) {
EventQueue.invokeLater(()->{
JFrame frame = new MainFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
);
// TODO Auto-generated method stub
}
}