Reputation: 8648
I want to make it like when I click a button, it will create a new file. Then the jTree will highlight the new file. Below are my code. Currently I create new file, i will show the new file but no highlight the file.
class FileTreeModel implements TreeModel {
private FileNode root;
public FileTreeModel(String directory) {
root = new FileNode(directory);
}
public Object getRoot() {
return root;
}
public Object getChild(Object parent, int index) {
FileNode parentNode = (FileNode) parent;
return new FileNode(parentNode, parentNode.listFiles()[index].getName());
}
public int getChildCount(Object parent) {
FileNode parentNode = (FileNode) parent;
if (parent == null || !parentNode.isDirectory()
|| parentNode.listFiles() == null) {
return 0;
}
return parentNode.listFiles().length;
}
public boolean isLeaf(Object node) {
return (getChildCount(node) == 0);
}
public int getIndexOfChild(Object parent, Object child) {
FileNode parentNode = (FileNode) parent;
FileNode childNode = (FileNode) child;
return Arrays.asList(parentNode.list()).indexOf(childNode.getName());
}
public void valueForPathChanged(TreePath path, Object newValue) {
}
public void addTreeModelListener(TreeModelListener l) {
}
public void removeTreeModelListener(TreeModelListener l) {
}
}
class FileNode extends java.io.File {
public FileNode(String directory) {
super(directory);
}
public FileNode(FileNode parent, String child) {
super(parent, child);
}
@Override
public String toString() {
return getName();
}
}
jTree = new JTree();
jTree.setBounds(new Rectangle(164, 66, 180, 421));
jTree.setBackground(SystemColor.inactiveCaptionBorder);
jTree.setBorder(BorderFactory.createTitledBorder(null, "",
TitledBorder.LEADING, TitledBorder.TOP, new Font("Arial",
Font.BOLD, 12), new Color(0, 0, 0)));
FileTreeModel model = new FileTreeModel(root);
jTree.setRootVisible(false);
jTree.setModel(model);
expandAll(jTree);
public void expandAll(JTree tree) {
int row = 0;
while (row < tree.getRowCount()) {
tree.expandRow(row);
row++;
}
}
Upvotes: 0
Views: 659
Reputation: 5538
I think you could use the setSelectedRow
[1] function.
EDIT: Added a sketch for the solution
You need to have a tree model
that will read the files from the file system (original source):
import java.io.File;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
class FileSystemModel implements TreeModel {
private File root;
private Vector listeners = new Vector();
public FileSystemModel(File rootDirectory) {
root = rootDirectory;
}
public Object getRoot() {
return root;
}
public Object getChild(Object parent, int index) {
File directory = (File) parent;
String[] children = directory.list();
return new File(directory, children[index]);
}
public int getChildCount(Object parent) {
File file = (File) parent;
if (file.isDirectory()) {
String[] fileList = file.list();
if (fileList != null)
return file.list().length;
}
return 0;
}
public boolean isLeaf(Object node) {
File file = (File) node;
return file.isFile();
}
public int getIndexOfChild(Object parent, Object child) {
File directory = (File) parent;
File file = (File) child;
String[] children = directory.list();
for (int i = 0; i < children.length; i++) {
if (file.getName().equals(children[i])) {
return i;
}
}
return -1;
}
public void valueForPathChanged(TreePath path, Object value) {
File oldFile = (File) path.getLastPathComponent();
String fileParentPath = oldFile.getParent();
String newFileName = (String) value;
File targetFile = new File(fileParentPath, newFileName);
oldFile.renameTo(targetFile);
File parent = new File(fileParentPath);
int[] changedChildrenIndices = { getIndexOfChild(parent, targetFile) };
Object[] changedChildren = { targetFile };
fireTreeNodesChanged(path.getParentPath(), changedChildrenIndices, changedChildren);
}
private void fireTreeNodesChanged(TreePath parentPath, int[] indices, Object[] children) {
TreeModelEvent event = new TreeModelEvent(this, parentPath, indices, children);
Iterator iterator = listeners.iterator();
TreeModelListener listener = null;
while (iterator.hasNext()) {
listener = (TreeModelListener) iterator.next();
listener.treeNodesChanged(event);
}
}
public void addTreeModelListener(TreeModelListener listener) {
listeners.add(listener);
}
public void removeTreeModelListener(TreeModelListener listener) {
listeners.remove(listener);
}
}
Then you would create a button listener to create the new file:
private void myButtonActionPerformed(java.awt.event.ActionEvent evt) {
File f = new File(MY_DIR + "/file" + new Random().nextInt());
try {
f.createNewFile();
FileSystemModel model = new FileSystemModel(new File(MY_DIR));
tree.setModel(model);
File root = (File) tree.getModel().getRoot();
TreePath path = getPathFor(model, root, f);
tree.expandPath(path);
tree.setSelectionPath(path);
}
catch (IOException e)
{
}
}
Finally you would return the TreePath
for the newly created file:
private TreePath getPathFor(FileSystemModel model, File root, File searched)
{
TreePath path = getPath(model, null, root, searched);
return path;
}
private TreePath getPath(FileSystemModel model, TreePath path, File parent, File searched)
{
if (path == null)
{
path = new TreePath(parent);
}
else if (parent.isDirectory())
{
path = path.pathByAddingChild(parent);
}
if (parent.getAbsolutePath().equals(searched.getAbsolutePath()))
{
return path.pathByAddingChild(parent);
}
for (int i = 0; i < model.getChildCount(parent); i++)
{
File child = ((File)model.getChild(parent, i)).getAbsoluteFile();
TreePath found = getPath(model, path, child, searched);
if (found != null)
{
return found;
}
}
return null;
}
This is just a demo on how you could do it, though its highly inneficient, because it recreates the model every time. I'm sure you can come up with a better solution.
Upvotes: 2