When I retrieve 1000+ java objects from the database, it is done very quickly. I end up with List<Object>
matching my query.
The problem is drawing these objects onto the Jtree
.
For example, I have a parentID of a given node. When this node (DefaultMutableTreeNode
) is double clicked (TreeMouseListener.class
), it will display direct children of this node, not all descendants (although this might be required later if possible but not right now).
The problem is that this jtree drawing operation takes very long time to complete adding 1000+ children DefaultMutableTreeNodes
for the selected parent node.
ex) 1000 of new DefaultMutableTreeNode(Person person);
How can this drawing process be sped up?
I am not using any custom cell renderer nor am I displaying anything other than small bits of text for each node.
You'll need to time where the slowdown is but I doubt it is just creating DefaultMutableTreeNodes which should be faster than loading the Person objects from the database. It's unlikely to be the painting (unless your Person#toString() is very slow) since there won't be a thousand nodes on the screen.
My guess is that you are adding the nodes one-by-one, causing a thousand change events instead of adding all the children at once. You should add the thousand child nodes to the parent node directly and then call DefaultTreeModel#nodeStructureChanged(node) on the parent node.
If that is still slow, it's time for a SSCCE. For example, pressing the button on my system shows no delay at all:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
public class TestJTree {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
final DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
final DefaultTreeModel model = new DefaultTreeModel(root);
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(new JScrollPane(new JTree(model)));
frame.getContentPane().add(new JButton(
new AbstractAction("Add thousand children") {
@Override
public void actionPerformed(ActionEvent e) {
int offset = root.getChildCount() + 1;
for (int i = 0; i < 1000; i++) {
DefaultMutableTreeNode child = new DefaultMutableTreeNode(
"Person " + (i + offset));
// adding child with event (but isn't much slower really)
// model.insertNodeInto(child, root, root.getChildCount());
root.add(child);
}
model.nodeStructureChanged(root);
}
}), BorderLayout.PAGE_END);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
You're probably creating 1000+ DefaultMutableTreeNodes to put your List in. The problem is creating that many objects quickly, and translating your objects to DefaultMutableTreeNode. If you don't create all of those objects you can improve your performance. I'd suggest just writing your own implementation of TreeModel that works directly with your object model so you don't have to recreate that many objects over again. That should improve your speed dramatically. I've put 10,000 objects in JTree before (I did it but it probably wasn't that great an idea), but I had to write my own TreeModel so I didn't have to recreate those objects.
However, as with all performance problems you should profile it first to figure out where you are spending time and address that issue. If it turns out it's this problem then you can do that. You don't need to try and create your own graphics drawing routines because that's significantly more work than writing your own TreeModel.
Another option is to fetch the tree on demand as it's needed. So fetch the root then as the user expands each node fetch its children from the server. The user can't look at all 1000+ nodes at once anyway so this will dramatically reduce the amount you are transferring over the network and less time spent on the server.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With