⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filesystemmodel2.java

📁 一个结java树和表格的控件
💻 JAVA
字号:
import java.io.IOException;import java.io.File;import java.util.Date;import java.util.Stack;import javax.swing.SwingUtilities;import javax.swing.tree.TreePath;public class FileSystemModel2 extends AbstractTreeTableModel {	// Names of the columns.	static protected String[] cNames = { "Name", "Size", "Type", "Modified" };	// Types of the columns.	static protected Class[] cTypes = { TreeTableModel.class, Integer.class,			String.class, Date.class };	// The the returned file length for directories.	public static final Integer ZERO = new Integer(0);	/** An array of MergeSorter sorters, that will sort based on size. */	static Stack sorters = new Stack();	/**	 * True if the receiver is valid, once set to false all Threads loading	 * files will stop.	 */	protected boolean isValid;	/**	 * Node currently being reloaded, this becomes somewhat muddy if reloading	 * is happening in multiple threads.	 */	protected FileNode reloadNode;	/** > 0 indicates reloading some nodes. */	int reloadCount;	/** Returns true if links are to be descended. */	protected boolean descendLinks;	/**	 * Returns a MergeSort that can sort on the totalSize of a FileNode.	 */	protected static MergeSort getSizeSorter() {		synchronized (sorters) {			if (sorters.size() == 0) {				return new SizeSorter();			}			return (MergeSort) sorters.pop();		}	}	/**	 * Should be invoked when a MergeSort is no longer needed.	 */	protected static void recycleSorter(MergeSort sorter) {		synchronized (sorters) {			sorters.push(sorter);		}	}	public FileSystemModel2() {		this(File.separator);	}	public FileSystemModel2(String rootPath) {		super(null);		isValid = true;		root = new FileNode(new File(rootPath));	}	public int getChildCount(Object node) {		Object[] children = getChildren(node);		return (children == null) ? 0 : children.length;	}	public Object getChild(Object node, int i) {		return getChildren(node)[i];	}	public boolean isLeaf(Object node) {		return ((FileNode) node).isLeaf();	}	public int getColumnCount() {		return cNames.length;	}	public String getColumnName(int column) {		return cNames[column];	}	public Class getColumnClass(int column) {		return cTypes[column];	}	public Object getValueAt(Object node, int column) {		FileNode fn = (FileNode) node;		try {			switch (column) {			case 0:				return fn.getFile().getName();			case 1:				if (fn.isTotalSizeValid()) {					return new Integer((int) ((FileNode) node).totalSize());				}				return null;			case 2:				return fn.isLeaf() ? "File" : "Directory";			case 3:				return fn.lastModified();			}		} catch (SecurityException se) {		}		return null;	}	public void reloadChildren(Object node) {		FileNode fn = (FileNode) node;		synchronized (this) {			reloadCount++;		}		fn.resetSize();		new Thread(new FileNodeLoader((FileNode) node)).start();	}	public void stopLoading() {		isValid = false;		synchronized (this) {			while (reloadCount > 0) {				try {					wait();				} catch (InterruptedException ie) {				}			}		}		isValid = true;	}	public void setDescendsLinks(boolean newValue) {		descendLinks = newValue;	}	public boolean getDescendsLinks() {		return descendLinks;	}	public String getPath(Object node) {		return ((FileNode) node).getFile().getPath();	}	public long getTotalSize(Object node) {		return ((FileNode) node).totalSize();	}	public boolean isReloading() {		return (reloadCount > 0);	}	public TreePath getPathLoading() {		FileNode rn = reloadNode;		if (rn != null) {			return new TreePath(rn.getPath());		}		return null;	}	public Object getNodeLoading() {		return reloadNode;	}	protected File getFile(Object node) {		FileNode fileNode = ((FileNode) node);		return fileNode.getFile();	}	protected Object[] getChildren(Object node) {		FileNode fileNode = ((FileNode) node);		return fileNode.getChildren();	}	protected static FileNode[] EMPTY_CHILDREN = new FileNode[0];	static private MergeSort fileMS = new MergeSort() {		public int compareElementsAt(int beginLoc, int endLoc) {			return ((String) toSort[beginLoc])					.compareTo((String) toSort[endLoc]);		}	};	class FileNode {		/** java.io.File the receiver represents. */		protected File file;		/** Parent FileNode of the receiver. */		private FileNode parent;		/** Children of the receiver. */		protected FileNode[] children;		/** Size of the receiver and all its children. */		protected long totalSize;		/** Valid if the totalSize has finished being calced. */		protected boolean totalSizeValid;		/** Path of the receiver. */		protected String canonicalPath;		/**		 * True if the canonicalPath of this instance does not start with the		 * canonical path of the parent.		 */		protected boolean isLink;		/** Date last modified. */		protected Date lastModified;		protected FileNode(File file) {			this(null, file);		}		protected FileNode(FileNode parent, File file) {			this.parent = parent;			this.file = file;			try {				canonicalPath = file.getCanonicalPath();			} catch (IOException ioe) {				canonicalPath = "";			}			if (parent != null) {				isLink = !canonicalPath.startsWith(parent.getCanonicalPath());			} else {				isLink = false;			}			if (isLeaf()) {				totalSize = file.length();				totalSizeValid = true;			}		}		/**		 * Returns the date the receiver was last modified.		 */		public Date lastModified() {			if (lastModified == null && file != null) {				lastModified = new Date(file.lastModified());			}			return lastModified;		}		/**		 * Returns the the string to be used to display this leaf in the JTree.		 */		public String toString() {			return file.getName();		}		/**		 * Returns the java.io.File the receiver represents.		 */		public File getFile() {			return file;		}		/**		 * Returns size of the receiver and all its children.		 */		public long totalSize() {			return totalSize;		}		/**		 * Returns the parent of the receiver.		 */		public FileNode getParent() {			return parent;		}		/**		 * Returns true if the receiver represents a leaf, that is it is isn't a		 * directory.		 */		public boolean isLeaf() {			return file.isFile();		}		/**		 * Returns true if the total size is valid.		 */		public boolean isTotalSizeValid() {			return totalSizeValid;		}		/**		 * Clears the date.		 */		protected void resetLastModified() {			lastModified = null;		}		/**		 * Sets the size of the receiver to be 0.		 */		protected void resetSize() {			alterTotalSize(-totalSize);		}		/**		 * Loads the children, caching the results in the children instance		 * variable.		 */		protected FileNode[] getChildren() {			return children;		}		/**		 * Recursively loads all the children of the receiver.		 */		protected void loadChildren(MergeSort sorter) {			totalSize = file.length();			children = createChildren(null);			for (int counter = children.length - 1; counter >= 0; counter--) {				Thread.yield(); // Give the GUI CPU time to draw itself.				if (!children[counter].isLeaf()						&& (descendLinks || !children[counter].isLink())) {					children[counter].loadChildren(sorter);				}				totalSize += children[counter].totalSize();				if (!isValid) {					counter = 0;				}			}			if (isValid) {				if (sorter != null) {					sorter.sort(children);				}				totalSizeValid = true;			}		}		/**		 * Loads the children of of the receiver.		 */		protected FileNode[] createChildren(MergeSort sorter) {			FileNode[] retArray = null;			try {				String[] files = file.list();				if (files != null) {					if (sorter != null) {						sorter.sort(files);					}					retArray = new FileNode[files.length];					String path = file.getPath();					for (int i = 0; i < files.length; i++) {						File childFile = new File(path, files[i]);						retArray[i] = new FileNode(this, childFile);					}				}			} catch (SecurityException se) {			}			if (retArray == null) {				retArray = EMPTY_CHILDREN;			}			return retArray;		}		/**		 * Returns true if the children have been loaded.		 */		protected boolean loadedChildren() {			return (file.isFile() || (children != null));		}		/**		 * Gets the path from the root to the receiver.		 */		public FileNode[] getPath() {			return getPathToRoot(this, 0);		}		/**		 * Returns the canonical path for the receiver.		 */		public String getCanonicalPath() {			return canonicalPath;		}		/**		 * Returns true if the receiver's path does not begin with the parent's		 * canonical path.		 */		public boolean isLink() {			return isLink;		}		protected FileNode[] getPathToRoot(FileNode aNode, int depth) {			FileNode[] retNodes;			if (aNode == null) {				if (depth == 0)					return null;				else					retNodes = new FileNode[depth];			} else {				depth++;				retNodes = getPathToRoot(aNode.getParent(), depth);				retNodes[retNodes.length - depth] = aNode;			}			return retNodes;		}		/**		 * Sets the children of the receiver, updates the total size, and if		 * generateEvent is true a tree structure changed event is created.		 */		protected void setChildren(FileNode[] newChildren, boolean generateEvent) {			long oldSize = totalSize;			totalSize = file.length();			children = newChildren;			for (int counter = children.length - 1; counter >= 0; counter--) {				totalSize += children[counter].totalSize();			}			if (generateEvent) {				FileNode[] path = getPath();				fireTreeStructureChanged(FileSystemModel2.this, path, null,						null);				FileNode parent = getParent();				if (parent != null) {					parent.alterTotalSize(totalSize - oldSize);				}			}		}		protected synchronized void alterTotalSize(long sizeDelta) {			if (sizeDelta != 0 && (parent = getParent()) != null) {				totalSize += sizeDelta;				nodeChanged();				parent.alterTotalSize(sizeDelta);			} else {				// Need a way to specify the root.				totalSize += sizeDelta;			}		}		/**		 * This should only be invoked on the event dispatching thread.		 */		protected synchronized void setTotalSizeValid(boolean newValue) {			if (totalSizeValid != newValue) {				nodeChanged();				totalSizeValid = newValue;				FileNode parent = getParent();				if (parent != null) {					parent.childTotalSizeChanged(this);				}			}		}		/**		 * Marks the receivers total size as valid, but does not invoke node		 * changed, nor message the parent.		 */		protected synchronized void forceTotalSizeValid() {			totalSizeValid = true;		}		/**		 * Invoked when a childs total size has changed.		 */		protected synchronized void childTotalSizeChanged(FileNode child) {			if (totalSizeValid != child.isTotalSizeValid()) {				if (totalSizeValid) {					setTotalSizeValid(false);				} else {					FileNode[] children = getChildren();					for (int counter = children.length - 1; counter >= 0; counter--) {						if (!children[counter].isTotalSizeValid()) {							return;						}					}					setTotalSizeValid(true);				}			}		}		/**		 * Can be invoked when a node has changed, will create the appropriate		 * event.		 */		protected void nodeChanged() {			FileNode parent = getParent();			if (parent != null) {				FileNode[] path = parent.getPath();				int[] index = { getIndexOfChild(parent, this) };				Object[] children = { this };				fireTreeNodesChanged(FileSystemModel2.this, path, index,						children);			}		}	}	class FileNodeLoader implements Runnable {		/** Node creating children for. */		FileNode node;		/** Sorter. */		MergeSort sizeMS;		FileNodeLoader(FileNode node) {			this.node = node;			node.resetLastModified();			node.setChildren(node.createChildren(fileMS), true);			node.setTotalSizeValid(false);		}		public void run() {			FileNode[] children = node.getChildren();			sizeMS = getSizeSorter();			for (int counter = children.length - 1; counter >= 0; counter--) {				if (!children[counter].isLeaf()) {					reloadNode = children[counter];					loadChildren(children[counter]);					reloadNode = null;				}				if (!isValid) {					counter = 0;				}			}			recycleSorter(sizeMS);			if (isValid) {				SwingUtilities.invokeLater(new Runnable() {					public void run() {						MergeSort sorter = getSizeSorter();						sorter.sort(node.getChildren());						recycleSorter(sorter);						node.setChildren(node.getChildren(), true);						synchronized (FileSystemModel2.this) {							reloadCount--;							FileSystemModel2.this.notifyAll();						}					}				});			} else {				synchronized (FileSystemModel2.this) {					reloadCount--;					FileSystemModel2.this.notifyAll();				}			}		}		protected void loadChildren(FileNode node) {			if (!node.isLeaf() && (descendLinks || !node.isLink())) {				final FileNode[] children = node.createChildren(null);				for (int counter = children.length - 1; counter >= 0; counter--) {					if (!children[counter].isLeaf()) {						if (descendLinks || !children[counter].isLink()) {							children[counter].loadChildren(sizeMS);						} else {							children[counter].forceTotalSizeValid();						}					}					if (!isValid) {						counter = 0;					}				}				if (isValid) {					final FileNode fn = node;					// Reset the children					SwingUtilities.invokeLater(new Runnable() {						public void run() {							MergeSort sorter = getSizeSorter();							sorter.sort(children);							recycleSorter(sorter);							fn.setChildren(children, true);							fn.setTotalSizeValid(true);							fn.nodeChanged();						}					});				}			} else {				node.forceTotalSizeValid();			}		}	}	static class SizeSorter extends MergeSort {		public int compareElementsAt(int beginLoc, int endLoc) {			long firstSize = ((FileNode) toSort[beginLoc]).totalSize();			long secondSize = ((FileNode) toSort[endLoc]).totalSize();			if (firstSize != secondSize) {				return (int) (secondSize - firstSize);			}			return ((FileNode) toSort[beginLoc]).toString().compareTo(					((FileNode) toSort[endLoc]).toString());		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -