I want to set for each node in my JTree a different icon, actually I'm loading each node from a data base, with a "while", I set each icon like a root, leaf or parent. Like this:
All my declarations are global:
private ResultSet myResultSet;
protected DefaultTreeModel treeModel;
private DefaultMutableTreeNode rootNode,childNode,parent1,parent2;
And this is the code where I set my nodes:
myResultSet=rtnNodes(); /*Method that returns a RS with my nodes*/
while(myResultSet.next()){
switch(myResultSet.getInt(1)){ /*The first column is the type of node: root, parent, leaf...*/
case 0: treeModel = new DefaultTreeModel((rootNode=new DefaultMutableTreeNode(myResultSet.getString(2)))); break; /*root node*/
case 1: case 4: parent1 = parent2 = makeNode(rootNode); break; /*parent node*/
case 2: makeNode(parent2); break; /*leaf node*/
case 3: parent2 = makeNode(parent1); break; /*sub patern node*/
} /*makeNode is the method where I create the nodes*/
}
The method makeNode is this:
public DefaultMutableTreeNode makeNode(DefaultMutableTreeNode parent){
//The second column in the RS is the name of the node
treeModel.insertNodeInto((childNode=new DefaultMutableTreeNode(myResultSet.getString(2))),parent,parent.getChildCount());
return childNode;
}
After to fill the treemodel with my nodes, I set the model to my JTree:
myJTree.setModel(treeModel);
myJTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
But the problem is. when I try to set the icons. I create a subclass called myTreeRenderer, and I use this:
myJTree.setCellRenderer(new treeRenderer());
But it doesn't set the icons as I want, the subclass is:
private ImageIcon root,parent,leaf;
public myTreeRenderer() {
root=setIcons(2); /*setIcons is a method that I dont publish in this post, that helps me to set the path of the icons*/
parent=setIcons(3);
leaf=setIcons(4);
}
#Override
public Component getTreeCellRendererComponent(JTree tree,Object value,boolean selected,boolean expanded,boolean leaf,int row,boolean hasFocus){
super.getTreeCellRendererComponent(tree,value,selected,expanded,leaf,row,hasFocus);
DefaultMutableTreeNode nodo = (DefaultMutableTreeNode)value;
TreeNode t = nodo.getParent();
if(t!=null){
setIcon(root);
}
return this;
}
How I can set the icon for each node without using his name? The code of the subclass, as is, set all the nodes with the same icon, and each time I selected a node in the jtree, the getTreeCellRendererComponent runs, I donĀ“t want this.
You can change default UI values for icons of JTree nodes without any custom renderer:
URL resource = logaff.class.getResource(IMAGE);
Icon icon = new ImageIcon(resource);
UIManager.put("Tree.closedIcon", icon);
UIManager.put("Tree.openIcon", icon);
UIManager.put("Tree.leafIcon", icon);
or use something like next:
#Override
public Component getTreeCellRendererComponent(JTree tree,
Object value, boolean selected, boolean expanded,
boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, selected,expanded, leaf, row, hasFocus);
DefaultMutableTreeNode nodo = (DefaultMutableTreeNode) value;
if (tree.getModel().getRoot().equals(nodo)) {
setIcon(root);
} else if (nodo.getChildCount() > 0) {
setIcon(parent);
} else {
setIcon(leaf);
}
return this;
}
Also read about rendering mechanism.
You can use it, a shorter way. "tree" is my JTree component.
DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) tree.getCellRenderer();
Icon closedIcon = new ImageIcon("closed.png");
Icon openIcon = new ImageIcon("open.png");
Icon leafIcon = new ImageIcon("leaf.png");
renderer.setClosedIcon(closedIcon);
renderer.setOpenIcon(openIcon);
renderer.setLeafIcon(leafIcon);
Related
I'm trying to visualize a JTree node as a JButton, I already tried creating a DefaultMutableTreeNode with a Jbutton object and the added it to the JTree:
JButton button = new JButton("Thing");
DefaultMutableTreeNode root = new DefaultMutableTreeNode(button);
JTree alberoClassi = new JTree(root);
These only show an error line with black parameters.
Searching the net I only found that I need a TreeRendererCell class, but none of the results show how to use it.
Are there some tutorials where I can find some examples to accomplish the task?
Finally I managed to solve the problem using an external class which implements the javax.swing.tree.TreeCellRenderer interface.
public class ClassCellRenderer implements javax.swing.tree.TreeCellRenderer {
JLabel className = new JLabel(" ");
JButton renderer = new JButton();
DefaultTreeCellRenderer defaultRenderer = new DefaultTreeCellRenderer();
public ClassCellRenderer() {
renderer.add(className);
}
#Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
Component returnValue = null;
if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
if (userObject instanceof String) {
String e = (String) userObject;
className.setText(e);
}
returnValue = renderer;
}
if (returnValue == null) {
returnValue = defaultRenderer.getTreeCellRendererComponent(tree, value, selected, expanded,
leaf, row, hasFocus);
}
return returnValue;
}
}
The JLabel and JButton could be changed with any other Component needed.
To add the renderer to the Tree, I used these lines:
alberoClassi = new JTree(root);
TreeCellRenderer renderer = new ClassCellRenderer();
alberoClassi.setCellRenderer(renderer); //aggiunta del renderer per i nodi
Here is my cell renderer class
public class MyCellRenderer extends DefaultTreeCellRenderer{
ImageIcon parentbill = new ImageIcon("images/parentbill.png");
ImageIcon childbill = new ImageIcon("images/childbill.png");
ImageIcon parentPurchase = new ImageIcon("images/parentexpense.png");
ImageIcon childPurchase = new ImageIcon("images/childexpense.png");
public MyCellRenderer(TreeTableController contr){
super();
}
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
Component c = super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
if(leaf){
setIcon(childPurchase);
//((DefaultTreeCellRenderer) c).setClosedIcon(parentPurchase);
}else{
setIcon(parentPurchase);
}
if(expanded){
setIcon(parentPurchase);
}
return c;
}
}
And there is how I add it:
TableModel tableModel = new TableModel(root);
JXTreeTable treeTable = new JXTreeTable(tableModel);
treeController = new TreeTableController(tableModel, treeTable);
MyCellRenderer cellRenderer = new MyCellRenderer(treeController);
treeController.getTable().setTreeCellRenderer(cellRenderer);
So, my renderer is supposed to change icons for the different kinds of rows in the table.
And, he does it(wow!). But he messes how table should look at the first place, he puts some java garbage in the first cell, like this:
How can i fix it? I know, there is a method to set icons from JXTreeTable without renderer, but i want to add some conditions depending on the type of the row, so I have to override it.
I have a JTree, based on several custom classes. I want to give several Nodes a specific icon. Therefore i did the following code based on this link: Dynamically change icon of specific nodes in JTree
DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer() {
private static final long serialVersionUID = 1L;
private Icon good = new ImageIcon(getClass().getResource("/good.png"));
private Icon dunno = new ImageIcon(getClass().getResource("/dunno.png"));
private Icon bad = new ImageIcon(getClass().getResource("/bad.png"));
#Override
public Component getTreeCellRendererComponent(JTree tree,
Object value, boolean selected, boolean expanded,
boolean isLeaf, int row, boolean focused) {
Component c = super.getTreeCellRendererComponent(tree, value, selected, expanded, isLeaf, row, focused);
// JTreePanelNode node = (JTreePanelNode)c; - not possible
return c;
}
};
this.getTree().setCellRenderer(renderer);
Each of my Nodes is an object of JTreePanelNode (custom class), which saves a specific state which can be set via setState(String s) and get via getState(). So what i want is to something like this:
if(node.getState().equals("good")) ..
else if(node.getState.equals("bad")) ..
else ..
How can i achieve something like that? From what i understand the renderer goes through every node with getTreeCellRendererComponent and applies a specific icon which i can choose with setIcon and several ifs(). However i cannot cast to JTreePanelNode. Any solution? Thanks :)
All depends on your JTreePanelNode Class. if it implements the TreeNode interface you are good to go with:
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean sel, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
Component comp = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf,
row, hasFocus);
TreeNode current = (TreeNode)value;
if (leaf) {
//set leaf icon
} else if (expanded) {
//set expanded icon
} else {
// set default state
}
if (hasFocus)
//set what it looks like if focused
else if (selected)
//set what it looks like if selected
else
//set default l&f
comp.setIcon(whatevericonset in above conditions);
return comp;
}
Of course you can add many more states depending on your node class.getState().
you can get access to the Object represented in that tree:
#Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean isLeaf, int row, boolean focused) {
Component c = super.getTreeCellRendererComponent(tree, value, selected, expanded, isLeaf, row, focused);
DefaultMutableTreeNode node = (DefaultMutableTreeNode ) value;
Object representedObject = node.getUserObject();
JLabel superLabel = super.getTreeCellRendererComponent();
String text = label.getText();
if(object.isGood() ){ //i don't know your code
superLabel .setText (text +"goooooooood");
}else{
superLabel .setText (text +"badbadbabd");
}
return superLabel ;
}
I rendered a check box node tree.
The renderer renders the parent nodes with a (check box + folder like icon ) and the leaf nodes as (Only check box) .
I have rendered it and now i want to make it editable . (i.e) when i click it , the check boxes must be checked and unchecked .
I tried writing an editor . But i am not clear as to how to write it . Please guide me as to how to accomplish this .
Many thanks in advance .
I have built the tree from a Vector . The vector is called NamedVector and it contains Parent node objects . The parent node object holds the leaf nodes . The leaf nodes are of type CheckBoxNode.
public class CheckBoxNodeRenderer implements TreeCellRenderer{
NonLeafRenderer nonLeafRenderer = new NonLeafRenderer();
protected JCheckBox check;
protected JLabel label;
public JPanel panel;
CheckBoxNode checkNode;
public JCheckBox getLeafRenderer()
{
return leafRenderer;
}
public CheckBoxNodeRenderer()
{
panel = new JPanel();
panel.setLayout(new BorderLayout());
check = new JCheckBox();
label = new JLabel();
Font fontValue;
fontValue = UIManager.getFont("Tree.font");
if (fontValue != null) {
leafRenderer.setFont(fontValue);
}
Boolean booleanValue = (Boolean) UIManager
.get("Tree.drawsFocusBorderAroundIcon");
leafRenderer.setFocusPainted((booleanValue != null)
&& (booleanValue.booleanValue()));
selectionBorderColor = UIManager.getColor("Tree.selectionBorderColor");
selectionForeground = UIManager.getColor("Tree.selectionForeground");
selectionBackground = UIManager.getColor("Tree.selectionBackground");
textForeground = UIManager.getColor("Tree.textForeground");
textBackground = UIManager.getColor("Tree.textBackground");
}
///////////////////
/**
* Approach by returning a panel .
*/
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean isSelected, boolean expanded,
boolean leaf, int row, boolean hasFocus) {
String stringValue = tree.convertValueToText(value, isSelected,
expanded, leaf, row, hasFocus);
panel.setEnabled(true);
if(leaf){
if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
checkNode = (CheckBoxNode)node.getUserObject();
check.setSelected(checkNode.isSelected());
label.setFont(tree.getFont());
label.setText(value.toString());
label.setIcon(null);
panel.removeAll();
panel.add(check,BorderLayout.WEST);
panel.add(label);
panel.setVisible(true);
}
}
else if(!leaf){
if ((value != null) && (value instanceof DefaultMutableTreeNode) ) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
Object parent = (Object)node.getUserObject();
System.err.println(parent.toString());
NamedVector parentNode = (NamedVector) parent;
check.setSelected(parentNode.isSelected());
label.setFont(tree.getFont());
label.setText(parentNode.toString());
label.setIcon(UIManager.getIcon("Tree.openIcon"));
panel.removeAll();
panel.add(check,BorderLayout.WEST);
panel.add(label);
panel.setVisible(true);
}
}
return panel;
}
The issue is that you're not listening for the events. In your getTreeCellRendererComponent method, create a listener and then make sure to tell the tree model that you've changed a node via the nodeChanged method. The following should work (you might have to make some variables final to use them in the inner class though):
check.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent ev) {
checkNode.setSelected(check.isSelected());
DefaultTreeModel dtm = (DefaultTreeModel)tree.getModel();
dtm.nodeChanged(node);
}
});
How can I get the text of selected item in a JTree?
From Java tutorial website on JTree:
//Where the tree is initialized:
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
//Listen for when the selection changes.
tree.addTreeSelectionListener(this);
public void valueChanged(TreeSelectionEvent e) {
//Returns the last path element of the selection.
//This method is useful only when the selection model allows a single selection.
DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
if (node == null)
//Nothing is selected.
return;
Object nodeInfo = node.getUserObject();
if (node.isLeaf()) {
BookInfo book = (BookInfo) nodeInfo;
displayURL(book.bookURL);
} else {
displayURL(helpURL);
}
}
DefaultMutableTreeNode selectedElement
=(DefaultMutableTreeNode)tree.getSelectionPath().getLastPathComponent();
.....
System.out.println(selectedElement.getUserObject());
//For multiple selection you can use
TreePath[] treePaths = tree.getSelectionModel().getSelectionPaths();
for (TreePath treePath : treePaths) {
DefaultMutableTreeNode selectedElement = (DefaultMutableTreeNode)treePath.getLastPathComponent();
Object userObject = selectedElement.getUserObject(); //Do what you want with selected element's user object
}
DefaultMutableTreeNode newchild=new DefaultMutableTreeNode(textField.getText());
DefaultMutableTreeNode SelectedNode= (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
DefaultTreeModel treemodel=(DefaultTreeModel) tree.getModel();
JOptionPane.showMessageDialog(null, SelectedNode.getUserObject().toString());
if(SelectedNode!=null)
treemodel.insertNodeInto(newchild, SelectedNode, SelectedNode.getChildCount());