How to collapse JTree nodes? - java

I want to implement a requirement where in I have to collapse all child nodes of JTree.
I am using jdk1.6.
Note: Only the child nodes of root element are to be collapsed on button click.
Here is my code:
private static void collapseAll(JTree tree, TreePath parent) {
TreeNode node = (TreeNode)parent.getLastPathComponent();
if (!node.isLeaf() && node.getChildCount()>=0) {
Enumeration e = node.children();
while (e.hasMoreElements()) {
TreeNode n = (TreeNode)e.nextElement();
TreePath path = parent.pathByAddingChild(n);
collapseAll(tree, path);
}
}
tree.collapsePath(parent);
}

If I understand your requirement you might be able to use the following code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TreeCollapseTest {
private final JTree tree = new JTree();
public JComponent makeUI() {
JPanel p = new JPanel(new BorderLayout());
p.add(new JButton(new AbstractAction("collapse") {
#Override public void actionPerformed(ActionEvent e) {
// if (tree.isRootVisible()) {
int row = tree.getRowCount() - 1;
//while (row >= 0) { //collapses all nodes
while (row > 0) { //collapses only child nodes of root node
tree.collapseRow(row);
row--;
}
}
}), BorderLayout.SOUTH);
p.add(new JScrollPane(tree));
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new TreeCollapseTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}

Try this:
for(int i = jTree.getRowCount() - 1; i >= 0; i--){
jTree.collapseRow(i);
}

Related

JTextArea - selection behavior on double / triple click + moving mouse

The problem: when you double click on word in JTextArea it is marked, but when you don't release the mouse button and try to mark next word, it is not marking whole word, but single characters instead.
It should mark the whole words (not single characters) when moving mouse (on double click). That's literally the default behavior in all programs which I tried, like: Notepad, Firefox, Chrome, Word, even Netbeans, etc.
Same thing with triple click (when holding and moving the mouse should mark the next line, not characters).
Any ideas? I had hard time Googling this, but since it's a very common thing I believe there must be a simple option or at least someone already have a solution.
Sample code:
public class TestJTextArea
{
public static void main(final String[] args)
{
final JPanel panel = new JPanel(new BorderLayout());
panel.setPreferredSize(new Dimension(500, 500));
panel.add(new JTextArea(), BorderLayout.CENTER);
final JFrame frame = new JFrame("Test");
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Maybe you need to create a customized Caret, for example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class TestJTextArea2 {
public Component makeUI() {
String text = "The quick brown fox jumps over the lazy dog.";
JTextArea textArea1 = new JTextArea("default\n" + text);
JTextArea textArea2 = new JTextArea("setCaret\n" + text) {
#Override public void updateUI() {
setCaret(null);
super.updateUI();
Caret oldCaret = getCaret();
int blinkRate = oldCaret.getBlinkRate();
Caret caret = new SelectWordCaret();
caret.setBlinkRate(blinkRate);
setCaret(caret);
}
};
JPanel p = new JPanel(new GridLayout(2, 1));
p.add(new JScrollPane(textArea1));
p.add(new JScrollPane(textArea2));
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new TestJTextArea2().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
class SelectWordCaret extends DefaultCaret {
private boolean wordSelectingMode = false;
private int p0; // = Math.min(getDot(), getMark());
private int p1; // = Math.max(getDot(), getMark());
#Override public void mousePressed(MouseEvent e) {
super.mousePressed(e);
int nclicks = e.getClickCount();
if (SwingUtilities.isLeftMouseButton(e) && !e.isConsumed() && nclicks == 2) {
p0 = Math.min(getDot(), getMark());
p1 = Math.max(getDot(), getMark());
wordSelectingMode = true;
} else {
wordSelectingMode = false;
}
}
#Override public void mouseDragged(MouseEvent e) {
if (wordSelectingMode && !e.isConsumed() && SwingUtilities.isLeftMouseButton(e)) {
continuouslySelectWords(e);
} else {
super.mouseDragged(e);
}
}
private void continuouslySelectWords(MouseEvent e) {
Position.Bias[] biasRet = new Position.Bias[1];
JTextComponent c = getComponent();
int pos = c.getUI().viewToModel2D(c, e.getPoint(), biasRet);
if(biasRet[0] == null) {
biasRet[0] = Position.Bias.Forward;
}
try {
if (p0 <= pos && pos <= p1) {
setDot(p0);
moveDot(p1, biasRet[0]);
} else if (p1 < pos) {
setDot(p0);
moveDot(Utilities.getWordEnd(c, pos - 1), biasRet[0]);
} else if (p0 > pos) {
setDot(p1);
moveDot(Utilities.getWordStart(c, pos), biasRet[0]);
}
} catch (BadLocationException bl) {
UIManager.getLookAndFeel().provideErrorFeedback(c);
}
}
}

Swing - JTree multiple root folders selected from JFileChooser

I am beginner in Swings. Trying to build a small application on JTree. Stuck with this issue.
I am able to load a selected folder using JFileChooser to the tree, but if I open one more folder, previous folder is replaced with the new folder. Is there any way we can open multiple folders in tree? As I keep opening folders from file chooser, it has to keep adding to existing tree. Please suggest how to achieve this?
Here is the working example I tried (picked from other posts):
import javax.swing.*;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.File;
public class TreeFrame {
public static void main(String[] args) {
JFrame frame = createFrame();
JPanel browsePanel = new JPanel();
JButton open = new JButton();
open.setPreferredSize(new Dimension(70, 25));
open.setText("Open");
final JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
JTree tree = new JTree();
JScrollPane scrollPane = new JScrollPane(tree);
Action action = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
int result = fileChooser.showOpenDialog(frame);
if (result == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
TreeModel model = new FileTreeModel(file);
tree.setModel(model);
scrollPane.add(tree);
}
}
};
open.addActionListener(action);
browsePanel.add(open);
frame.add(browsePanel, BorderLayout.WEST);
frame.add(scrollPane, BorderLayout.EAST);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static JFrame createFrame() {
JFrame frame = new JFrame("JTree Expand/Collapse example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(500, 400));
frame.setLayout(new GridLayout(1, 2));
return frame;
}
static class FileTreeModel implements TreeModel {
protected File root;
public FileTreeModel(File root) { this.root = root; }
public Object getRoot() { return root; }
public boolean isLeaf(Object node) { return ((File)node).isFile(); }
public int getChildCount(Object parent) {
String[] children = ((File)parent).list();
if (children == null) return 0;
return children.length;
}
public Object getChild(Object parent, int index) {
String[] children = ((File)parent).list();
if ((children == null) || (index >= children.length)) return null;
return new File((File) parent, children[index]);
}
public int getIndexOfChild(Object parent, Object child) {
String[] children = ((File)parent).list();
if (children == null) return -1;
String childname = ((File)child).getName();
for(int i = 0; i < children.length; i++) {
if (childname.equals(children[i])) return i;
}
return -1;
}
public void valueForPathChanged(TreePath path, Object newvalue) {}
public void addTreeModelListener(TreeModelListener l) {}
public void removeTreeModelListener(TreeModelListener l) {}
}
}
Thanks for the suggestion, found solution:
DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode)model.getRoot();
root.add(addNodes(null, file));
model.reload(root);

Drag and Drop from JTree to JList with own objects

I have a JTree with DefaultMutableTreeNodes. On some levels these nodes were initialized with my own serializable objects. In total there are two different types of objects (called "Step" and "Order"). I want to be able to drop only nodes which were initialized with either of these two objects. Any other nodes which are just Strings shouldn't be droppable. One "Order" can contain many "Steps". I want to be able to drag them onto a JPanel were they get inserted into a JList. If a "Order" was dropped all of the "Steps" are supposed to be inserted, if only a "Step" was dropped only that particular "Step" is supposed to be inserted.
SSCCE below!
JTree:
tree = new JTree();
tree.setShowsRootHandles(true);
tree.setRootVisible(false);
tree.setDragEnabled(true);
tree.setModel(treeModel);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
JPanel:
public class TablePanel extends JPanel
{
private static final long serialVersionUID = 3216206960422611905L;
public TablePanel()
{
super();
setLayout(new MigLayout("", "[grow]", "[][grow]"));
JProgressBar progressBar = new JProgressBar();
progressBar.setMaximum(28800); // 8 hours in seconds
progressBar.setStringPainted(true);
add(progressBar, "cell 0 0,growx");
DefaultListModel<Step> listModel = new DefaultListModel<Step>();
JList<Step> list = new JList<Step>();
list.setModel(listModel);
setDropTarget(new DropTarget(this, TransferHandler.COPY, new DropTargetAdapter()
{
private int index = 0;
private int amount = 0;
#Override
public void drop(DropTargetDropEvent dtde)
{
amount = 0;
index = 0;
}
#Override
public void dragExit(DropTargetEvent dte)
{
if (listModel.size() > 0)
{
if (amount == 1)
{
listModel.remove(index);
}
else
{
for (int i = 0; i < amount; i++)
{
listModel.remove(index + i);
}
}
amount = 0;
}
}
#Override
public void dragEnter(DropTargetDragEvent dtde)
{
try
{
Transferable tr = dtde.getTransferable();
if (dtde.isDataFlavorSupported(Order.auftragFlavor))
{
Order a = (Order) tr.getTransferData(Order.auftragFlavor); // Wrong, how do I get this?
dtde.acceptDrag(DnDConstants.ACTION_COPY);
amount = a.getSteps().size();
}
else if (dtde.isDataFlavorSupported(Step.arbeitsgangFlavor))
{
Step ag = (Step) tr.getTransferData(Step.arbeitsgangFlavor);
dtde.acceptDrag(DnDConstants.ACTION_COPY);
amount = 1;
}
else
{
dtde.rejectDrag();
}
}
catch (Exception e)
{
e.printStackTrace();
dtde.rejectDrag();
}
}
#Override
public void dragOver(DropTargetDragEvent dtde)
{
try
{
Transferable tr = dtde.getTransferable();
if (dtde.isDataFlavorSupported(Order.auftragFlavor))
{
Order a = (Order) tr.getTransferData(Order.auftragFlavor); // Wrong, how do I get this?
dtde.acceptDrag(DnDConstants.ACTION_COPY);
amount = a.getSteps().size();
}
else if (dtde.isDataFlavorSupported(Step.arbeitsgangFlavor))
{
Step ag = (Step) tr.getTransferData(Step.arbeitsgangFlavor);
dtde.acceptDrag(DnDConstants.ACTION_COPY);
amount = 1;
}
else dtde.rejectDrag();
}
catch (Exception e)
{
e.printStackTrace();
dtde.rejectDrag();
}
}
}, true, null));
add(list, "cell 0 1,grow");
}
}
When you are dragging over the JList, then the data should be inserted into the list to give the user feedback and the possibility to place it in the list. If not dropped, it should be removed again.
How can drag and drop my objects onto the JPanel, but not nodes which are just Strings?
EDIT:
With (String) tr.getTransferData(DataFlavor.stringFlavor) I am able to get the label of the node, but this is not really helpfull, because I don't know if it was a Order, Step or just a string node.
EDIT2 SSCCE:
public class Test extends JFrame
{
private static final long serialVersionUID = 1L;
private JPanel contentPane;
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
Test window = new Test();
window.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
public Test()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
DefaultMutableTreeNode string1 = new DefaultMutableTreeNode("String 1");
DefaultMutableTreeNode order1 = new DefaultMutableTreeNode(new ParentObject());
order1.add(new DefaultMutableTreeNode(new ChildObject()));
order1.add(new DefaultMutableTreeNode(new ChildObject()));
string1.add(order1);
root.add(string1);
DefaultTreeModel model = new DefaultTreeModel(root);
JTree tree = new JTree(model);
tree.setShowsRootHandles(true);
tree.setRootVisible(false);
tree.setDragEnabled(true);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
contentPane.add(tree, BorderLayout.WEST);
CustPanel panel = new CustPanel();
contentPane.add(panel, BorderLayout.CENTER);
}
}
class CustPanel extends JPanel
{
private static final long serialVersionUID = 1L;
public CustPanel()
{
super();
setLayout(new MigLayout("", "[grow]", "[][grow]"));
JProgressBar progressBar = new JProgressBar();
add(progressBar, "cell 0 0,growx");
DefaultListModel<ChildObject> listModel = new DefaultListModel<ChildObject>();
JList<ChildObject> list = new JList<ChildObject>();
list.setModel(listModel);
setDropTarget(new DropTarget(this, TransferHandler.COPY, new DropTargetAdapter()
{
#Override
public void drop(DropTargetDropEvent dtde)
{
Transferable tr = dtde.getTransferable();
if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor))
{
try
{
System.out.println((String) tr.getTransferData(DataFlavor.stringFlavor)); // I want the actual object
}
catch (UnsupportedFlavorException | IOException e)
{
e.printStackTrace();
}
}
}
#Override
public void dragExit(DropTargetEvent dte)
{
}
#Override
public void dragEnter(DropTargetDragEvent dtde)
{
Transferable tr = dtde.getTransferable();
if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor))
{
try
{
System.out.println((String) tr.getTransferData(DataFlavor.stringFlavor)); // I want the actual object
}
catch (UnsupportedFlavorException | IOException e)
{
e.printStackTrace();
}
}
}
#Override
public void dragOver(DropTargetDragEvent dtde)
{
Transferable tr = dtde.getTransferable();
if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor))
{
try
{
System.out.println((String) tr.getTransferData(DataFlavor.stringFlavor)); // I want the actual object
}
catch (UnsupportedFlavorException | IOException e)
{
e.printStackTrace();
}
}
}
}, true, null));
add(list, "cell 0 1,grow");
}
}
class ParentObject implements Serializable
{
private static final long serialVersionUID = 1279985471254050120L;
public ArrayList<ChildObject> getChildren()
{
return new ArrayList<ChildObject>();
}
#Override
public String toString()
{
return "ParentObject";
}
}
class ChildObject implements Serializable
{
private static final long serialVersionUID = -5833860202973614790L;
#Override
public String toString()
{
return "ChildObject";
}
}
but not nodes which are just Strings?
You might be able to use a TransferHandler#createTransferable(...) method to get the DefaultMutableTreeNode.
TransferHandler#createTransferable(JComponent) (Java Platform SE 8 )
Demo - DropDemo (The Java™ Tutorials > Creating a GUI With JFC/Swing > Drag and Drop and Data Transfer)
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.io.*;
import java.util.*;
import javax.activation.*;
import javax.swing.*;
import javax.swing.tree.*;
public class Test2 {
public JComponent makeUI() {
DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
DefaultMutableTreeNode string1 = new DefaultMutableTreeNode("String 1");
DefaultMutableTreeNode order1 = new DefaultMutableTreeNode(new ParentObject());
order1.add(new DefaultMutableTreeNode(new ChildObject()));
order1.add(new DefaultMutableTreeNode(new ChildObject()));
string1.add(order1);
root.add(string1);
DefaultTreeModel model = new DefaultTreeModel(root);
JTree tree = new JTree(model);
tree.setShowsRootHandles(true);
tree.setRootVisible(false);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setTransferHandler(new TreeTransferHandler());
tree.setDragEnabled(true);
DefaultListModel<ChildObject> listModel = new DefaultListModel<ChildObject>();
JList<ChildObject> list = new JList<ChildObject>();
list.setModel(listModel);
list.setDropTarget(new DropTarget(list, TransferHandler.COPY, new DropTargetAdapter() {
private void print(Transferable tr) {
try {
Object node = tr.getTransferData(TreeTransferHandler.FLAVOR);
System.out.println(node); // I want the actual object
} catch (UnsupportedFlavorException | IOException ex) {
ex.printStackTrace();
}
}
#Override
public void drop(DropTargetDropEvent dtde) {
if (dtde.isDataFlavorSupported(TreeTransferHandler.FLAVOR)) {
print(dtde.getTransferable());
}
}
#Override public void dragExit(DropTargetEvent dte) {}
#Override public void dragEnter(DropTargetDragEvent dtde) {}
#Override public void dragOver(DropTargetDragEvent dtde) {}
}, true, null));
JPanel contentPane = new JPanel(new GridLayout(1, 2));
contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
contentPane.add(new JScrollPane(tree), BorderLayout.WEST);
contentPane.add(new JScrollPane(list), BorderLayout.CENTER);
return contentPane;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override public void run() {
try {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new Test2().makeUI());
f.setBounds(100, 100, 450, 300);
f.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
class ParentObject implements Serializable {
public ArrayList<ChildObject> getChildren() {
return new ArrayList<ChildObject>();
}
#Override
public String toString() {
return "ParentObject";
}
}
class ChildObject implements Serializable {
#Override
public String toString() {
return "ChildObject";
}
}
class TreeTransferHandler extends TransferHandler {
public static final DataFlavor FLAVOR = new ActivationDataFlavor(
DefaultMutableTreeNode[].class,
DataFlavor.javaJVMLocalObjectMimeType,
"Array of DefaultMutableTreeNode");
#Override protected Transferable createTransferable(JComponent c) {
JTree source = (JTree) c;
TreePath[] paths = source.getSelectionPaths();
DefaultMutableTreeNode[] nodes = new DefaultMutableTreeNode[paths.length];
for (int i = 0; i < paths.length; i++) {
nodes[i] = (DefaultMutableTreeNode) paths[i].getLastPathComponent();
}
return new DataHandler(nodes, FLAVOR.getMimeType());
}
#Override public int getSourceActions(JComponent c) {
return TransferHandler.COPY;
}
}

Recursively reading a Directory into an ArrayList/Array in Java

I am currently stuck at reading a directory into an ArrayList or better an Array in Java.
I want to use the Data in a JTree.
That's the code I currently use:
//After the definiton of the Class
private ArrayList<File> files = new ArrayList<File>();
// In the main method
this.parse(new File("."));
DefaultMutableTreeNode root = processHierarchy(files.toArray());
this.tree = new JTree(root);
private void parse(File parent)
{
files.add(parent);
if(parent.isDirectory())
{
System.out.println("DIR: "+parent.getName());
String[] child = parent.list();
if(child != null)
{
for(int i = 0; i < child.length; i++)
{
File f = new File(parent, child[i]);
this.parse(f);
}
}
}
else
{
System.out.println("FILE: "+parent.getName());
}
}
Anyone got an idea?
I found this code online that searches a path and then displays it in a JTree.
import javax.swing.*;
import javax.swing.tree.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;
import java.io.*;
public class SimpleTree extends JPanel {
JTree tree;
DefaultMutableTreeNode root;
public SimpleTree() {
root = new DefaultMutableTreeNode("root", true);
getList(root, new File("C:\\Program Files")); // change path here
setLayout(new BorderLayout());
tree = new JTree(root);
tree.setRootVisible(false);
add(new JScrollPane((JTree)tree),"Center");
}
public Dimension getPreferredSize(){
return new Dimension(200, 120);
}
public void getList(DefaultMutableTreeNode node, File f) {
if(!f.isDirectory()) {
// We keep only JAVA source file for display in this HowTo
if (f.getName().endsWith("java")) {
System.out.println("FILE - " + f.getName());
DefaultMutableTreeNode child = new DefaultMutableTreeNode(f);
node.add(child);
}
}
else {
System.out.println("DIRECTORY - " + f.getName());
DefaultMutableTreeNode child = new DefaultMutableTreeNode(f);
node.add(child);
File fList[] = f.listFiles();
for(int i = 0; i < fList.length; i++)
getList(child, fList[i]);
}
}
public static void main(String s[]){
MyJFrame frame = new MyJFrame("Directory explorer");
}
}
class WindowCloser extends WindowAdapter {
public void windowClosing(WindowEvent e) {
Window win = e.getWindow();
win.setVisible(false);
System.exit(0);
}
}
class MyJFrame extends JFrame {
JButton b1, b2, b3;
SimpleTree panel;
MyJFrame(String s) {
super(s);
panel = new SimpleTree();
getContentPane().add(panel,"Center");
setSize(300,300);
setVisible(true);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowCloser());
}
}
Source: http://www.rgagnon.com/javadetails/java-0324.html

How do I auto-expand a JTree when setting a new TreeModel?

I have a custom JTree and a custom JModel; I would for the JTree to "auto-expand" when I give it a new model. At the moment, it simply collapse all the nodes to the root.
Here is an example:
private class CustomTree extends JTree {
#Override
public boolean isExpanded(TreePath path) {
return ((Person) path.getLastPathComponent).hasChildren();
}
private class CustomTreeModel extends TreeModel {
// ... omitting various implementation details
#Override
public boolean isLeaf(Object object) {
return !((Person) object).hasChildren();
}
}
Model model = new Model();
Person bob = new Person();
Person alice = new Person();
bob.addChild(alice);
model.setRoot(bob);
JTree tree = new CustomTree(new CustomTreeModel(model));
At this point, the tree correctly displays:
- BOB
- ALICE
where Alice is a child of Bob (both in the data and in the visual tree)
However, if I call:
tree.setModel(new CustomTreeModel(model));
everything is collapsed:
+ BOB
Is there a way to "auto-expand" everything in the tree when setting a new model?
The following worked for me (called after setting the new model):
for (int i = 0; i < tree.getRowCount(); i++) {
tree.expandRow(i);
}
I had a similar problem.
Your solution (as posted https://stackoverflow.com/a/15211697/837530) seemed to work for me only for the top level tree nodes.
But I needed to expand all the a descendants node. So I solved it with the following recursive method:
private void expandAllNodes(JTree tree, int startingIndex, int rowCount){
for(int i=startingIndex;i<rowCount;++i){
tree.expandRow(i);
}
if(tree.getRowCount()!=rowCount){
expandAllNodes(tree, rowCount, tree.getRowCount());
}
}
which is invoked with
expandAllNodes(tree, 0, tree.getRowCount());
where, tree is a JTree.
Unless someone has a better solution.
There's also this non-recursive version.
private void expandAllNodes(JTree tree) {
int j = tree.getRowCount();
int i = 0;
while(i < j) {
tree.expandRow(i);
i += 1;
j = tree.getRowCount();
}
}
this worked for me..
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.Enumeration;
public class JTreeNodeAutoExpandCollapse extends JFrame {
public JTreeNodeAutoExpandCollapse() throws HeadlessException {
initializeUI();
}
private void initializeUI() {
setSize(200, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode chapter1 = new DefaultMutableTreeNode("Chapter 1");
DefaultMutableTreeNode sub1 = new DefaultMutableTreeNode("1.1");
DefaultMutableTreeNode sub2 = new DefaultMutableTreeNode("1.2");
DefaultMutableTreeNode sub3 = new DefaultMutableTreeNode("1.3");
DefaultMutableTreeNode sub31 = new DefaultMutableTreeNode("1.3.1");
DefaultMutableTreeNode sub32 = new DefaultMutableTreeNode("1.3.2");
root.add(chapter1);
chapter1.add(sub1);
chapter1.add(sub2);
chapter1.add(sub3);
sub3.add(sub31);
sub3.add(sub32);
final JTree tree = new JTree(root);
expandTree(tree, false);
JScrollPane pane = new JScrollPane(tree);
pane.setPreferredSize(new Dimension(200, 200));
JPanel buttonPanel = new JPanel(new BorderLayout());
JButton expandAll = new JButton("Expand All");
expandAll.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
expandTree(tree, true);
}
});
JButton collapseAll = new JButton("Collapse All");
collapseAll.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
expandTree(tree, false);
}
});
buttonPanel.add(expandAll, BorderLayout.WEST);
buttonPanel.add(collapseAll, BorderLayout.EAST);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(pane, BorderLayout.CENTER);
getContentPane().add(buttonPanel, BorderLayout.SOUTH);
}
private void expandTree(JTree tree, boolean expand) {
TreeNode root = (TreeNode) tree.getModel().getRoot();
expandAll(tree, new TreePath(root), expand);
}
private void expandAll(JTree tree, TreePath path, boolean expand) {
TreeNode node = (TreeNode) path.getLastPathComponent();
if (node.getChildCount() >= 0) {
Enumeration enumeration = node.children();
while (enumeration.hasMoreElements()) {
TreeNode n = (TreeNode) enumeration.nextElement();
TreePath p = path.pathByAddingChild(n);
expandAll(tree, p, expand);
}
}
if (expand) {
tree.expandPath(path);
} else {
tree.collapsePath(path);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new JTreeNodeAutoExpandCollapse().setVisible(true);
}
});
}
}
public void expandTree(){
int row = 1;
while (row++ < tree.getRowCount()){
tree.expandRow(row);
}
public void collapseTree(){
int row = tree.getRowCount() - 1;
while (row-- > 0){
tree.collapseRow(row);
}
}

Categories