接着上篇 实现一个简单文件浏览器(2)
最后说下如何实现主窗口,这个主窗口的主要功能是整合上面两篇文章实现的文件树和文件列表,再添加一个JTextField控件显示当前浏览的路径,和后退按钮,返回上一次浏览的目录。
再看下实现的文件浏览器的效果:
我将整个窗口布局分成2块,后退按钮和文件目录框在顶部的Panel中,文件树和文件列表在底部的Panel中,底部Panel又分成两部分,分别容纳这两个控件
所以需要定义的控件和成员变量:
private JPanel pnlTop;
private JPanel pnlLeft;
private JPanel pnlRight;
private JSplitPane spBottom;
private JTextField tfDir;
private FileTreeNode fileTreeRoot;
private FileTree trFileTree;
private FileTable tbFile;
private Stack stackFile;
private JButton btnBack;
File[] fileRoots;
Object[][] initFileData;
JScrollPane spTable;
FileSystemView fileSystemView = FileSystemView.getFileSystemView();
由于有个后退功能,就需要个变量stackFile作为栈来存储浏览过的文件路径
初始化数据并创建控件:
private void initData(){
stackFile = new Stack();
// 获取系统根目录
fileRoots = fileSystemView.getRoots();
fileTreeRoot = new FileTreeNode(fileRoots[0], true);
// 获取根目录下所有文件夹
File[] files = fileSystemView.getFiles(fileRoots[0], false);
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory())
{
FileTreeNode childNode = new FileTreeNode(files[i], false);
fileTreeRoot.add(childNode);
}
}
// 获取根目录下的”我的电脑“目录下的文件目录列表,给文件列表初始化
File[] libFiles = fileSystemView.getFiles(files[3], false);
initFileData = new Object[libFiles.length][4];
for (int i=0; i < libFiles.length; i++){
for (int j = 0; j < 4; j++){
initFileData[i][j] = files[i];
}
}
}
private void createComponent(){
pnlTop = new JPanel();
pnlLeft = new JPanel();
pnlRight = new JPanel();
spBottom = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
tfDir = new JTextField();
trFileTree = new FileTree();
tbFile = new FileTable();
btnBack = new JButton("后退");
}
fileSystemView.getRoots()这个函数主要作用是返回系统的根目录(在windows中,这个根目录就是桌面路径)
注:File[] libFiles = fileSystemView.getFiles(files[3], false);这句话是获取windows中的”我的电脑“目录(我也不知道为什么是根目录下子目录的第3个位置呢。这是我试出来的)
接着给窗口控件布局:
这里主要是使用java 中的网格布局
网格布局:
将窗体划分成一个表格,可以在创建网格布局管理器时指定表格的行与列。默认的情况下是从左到右、从上到下组织增加到窗体中的控件的,而且每一个控件都会填充整个单元格,即改变窗体的大小时控件也会随之改变大小。
private void initComponent(){
initData();
createComponent();
AddComponentListener();
spTable = new JScrollPane(tbFile);
spTable.setBackground(Color.white);
// 设置table 列宽
DefaultTreeModel dfTreeModel = new DefaultTreeModel(fileTreeRoot) {
@Override
public boolean isLeaf(Object node) {
FileTreeNode treeNode = (FileTreeNode) node;
if (treeNode.isDummyRoot()){
return false;
}
return ((File)treeNode.getUserObject()).isFile();
}
};
trFileTree.setModel(dfTreeModel);
trFileTree.setCellRenderer(new FileTreeCellRenderer());
trFileTree.setRootVisible(false);
trFileTree.setSelectionRow(0);
JScrollPane scroll = new JScrollPane(trFileTree);
scroll.setLayout(new ScrollPaneLayout());
scroll.getViewport().setBackground(Color.WHITE);
pnlLeft.setLayout(new GridBagLayout());
pnlLeft.add(scroll, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.EAST,
GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
pnlRight.setLayout(new GridBagLayout());
pnlRight.add(spTable,new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.EAST,
GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
pnlTop.setLayout(new GridBagLayout());
pnlTop.add(btnBack, new GridBagConstraints(0, 0, 1, 1, 0.05, 1.0, GridBagConstraints.WEST,
GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
pnlTop.add(tfDir,new GridBagConstraints(1, 0, 1, 1, 0.95, 1.0, GridBagConstraints.EAST,
GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
spBottom.setLeftComponent(pnlLeft);
spBottom.setRightComponent(pnlRight);
pnlLeft.setMinimumSize(new Dimension(200,600));
Container container = this.getContentPane();
container.setLayout(new GridBagLayout());
container.add(pnlTop, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.05, GridBagConstraints.EAST,
GridBagConstraints.BOTH, new Insets(2, 0, 0, 0), 0, 0));
container.add(spBottom, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.95, GridBagConstraints.EAST,
GridBagConstraints.BOTH, new Insets(4, 2, 2, 2), 0, 0));
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
this.setBounds(screenSize.width/2 - 400, screenSize.height/2 - 300, 800, 600);
this.setMinimumSize(new Dimension(800, 600));
}
给控件添加事件监听:
private void AddComponentListener(){
trFileTree.addTreeSelectionListener(new TreeSelectionListener(){
@Override
public void valueChanged(TreeSelectionEvent e) {
JTree tree = (JTree)e.getSource();
FileTreeNode selectNode = (FileTreeNode)tree.getLastSelectedPathComponent();
if (selectNode != null){
File file = selectNode.getFile();
updateTable(file, false);
}
}
});
trFileTree.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 1)
{
JTree tree = (JTree)e.getSource();
FileTreeNode selectNode = (FileTreeNode)tree.getLastSelectedPathComponent();
if (selectNode != null){
File file = selectNode.getFile();
updateTable(file, false);
}
}
}
});
tbFile.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
FileTable fileTable = (FileTable)e.getSource();
int row = fileTable.rowAtPoint(e.getPoint());
File file = (File) fileTable.getValueAt(row, 0);
if (e.getClickCount() == 1){
// TreePath path =trFileTree.getSelectionPath();
// path.pathByAddingChild(new FileTreeNode(file));
// trFileTree.setSelectionPath(path);
} else if (e.getClickCount() == 2){
updateTable(file, false);
}
}
});
btnBack.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (stackFile.size()>1)
{
stackFile.pop();
updateTable(stackFile.peek(), true);
}
}
});
}
private void updateTable(File file, Boolean isBack){
String path = file.getAbsolutePath();
if (path == null)
return;
tfDir.setText(path);
File[] files = fileSystemView.getFiles(file, false);
if (!isBack){
stackFile.push(file);
}
Vector vFile = new Vector();
for (int i = 0; i < files.length; i++){
vFile.add(files[i]);
}
Collections.sort(vFile, FILE_COMPARATOR);
Object[][] fileData;
fileData = new Object[files.length][4];
for (int i = 0; i < fileData.length; i++){
for (int j = 0; j < 4; j++){
fileData[i][j] = vFile.elementAt(i);
}
}
FileTableModel model = new FileTableModel(fileData);
tbFile.setModel(model);
TableRowSorter sort = new TableRowSorter(model);
sort.setComparator(0, FILE_COMPARATOR);
tbFile.setRowSorter(sort);
// 设置table 列宽
tbFile.getColumnModel().getColumn(0).setPreferredWidth(200);
tbFile.getColumnModel().getColumn(1).setPreferredWidth(120);
tbFile.getColumnModel().getColumn(2).setPreferredWidth(100);
tbFile.getColumnModel().getColumn(3).setPreferredWidth(50);
spTable.getViewport().setBackground(Color.white);
}
public static final Comparator FILE_COMPARATOR= new Comparator() {
@Override
public int compare(File f1, File f2) {
if (f1.isDirectory()){
if (f2.isDirectory()){
return f1.getName().compareToIgnoreCase(f2.getName());
} else {
return -1;
}
} else {
if (!f2.isDirectory()){
return f1.getName().compareToIgnoreCase(f2.getName());
} else {
return 1;
}
}
}
};
FILE_COMPARATOR是个函数对象,重载了compare方法来比较文件大小,用来作为文件列表中第一列的排序的比较方法
项目的主函数:
package FileExplorerUI;
import javax.swing.*;
/**
* Created by Administrator on 2016/3/28.
*/
public class Main {
public static void main(String args[]){
setLookAndFeel();
final JFrame f=new FileExplorerWindow();
f.setVisible(true);
}
public static void setLookAndFeel() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
}
}
这里的setLookAndFeel()函数是将应用外观设置成你所使用的平台的外观(java的图形界面外观有3种,默认是java的金属外观,windows系统,motif系统外观)
整个项目的完整代码:Github链接
本文链接: www.bugcoding.com/entry/17
版权所有。转载时必须以链接形式注明作者和原始出处及本声明。