Alpha
Alpha

Reputation: 307

JTree Default icons not removed with Root Icon

I am aware that there are relevant materials exists on google about JTree icons change, but still I am unable to sort out my simple requirements.

I need to change the icon of Root element of JTree different than it's node & leaf. I manage to change the node & leaf icons, but the default arrow icons (red highlighted in picture) are still there & I have to click on it to drill down the tree whereas I want to click on custom image icons to drill down the tree.

enter image description here

    /** CHANGE JTREE DEFAULT ICONS  **/
        private class userRendererForTree extends DefaultTreeCellRenderer {
            private static final long serialVersionUID = 1L;
    
            public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
                    boolean leaf, int row, boolean hasFocus) {
    
                super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
                if (leaf) {
                    setIcon(setImageIcon(AppConstants.BOM_ROUTE_NODE_LEAF));
                } else {
                    setIcon(setImageIcon(AppConstants.BOM_ROUTE_NODE_RIGHT));
                }
                if (expanded) {
                    setIcon(setImageIcon(AppConstants.BOM_ROUTE_NODE_BOTTOM));
                }
                return this;
            }
        }

/**  LOAD IMAGE ICON FROM RESOURCES  **/
    private ImageIcon setImageIcon(String path){
        Image image = null;
        ImageIcon icon = null;
        try {
            image = LoadResource.getImageFromResourceAsURL(path);
            image = image.getScaledInstance(10, 10, Image.SCALE_SMOOTH);
            icon = new ImageIcon(image);
            return icon;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return icon;
    }

Calling of Renderer: -

JTree BomTree = new JTree(createTreeModel());
scrollPane.setColumnHeaderView(BomTree);
BomTree.setCellRenderer(new userRendererForTree());

UPDATED - enter image description here

Upvotes: 1

Views: 131

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347332

I apologies, you mean you want to replace the expand/collapse handles, not customise the expand/closed icons of the cell ... because JTree isn't confusing 🙄

In order to do this, you either need to supply your own look and feel implementation OR customise the existing UI properties.

Thanks to TrashGod, the second method is relatively easy, just remember, this will effect ALL JTrees in your application.

enter image description here

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.put("Tree.expandedIcon", new ImageIcon(ImageIO.read(getClass().getResource("/images/icons8-expand-arrow-24.png"))));
                    UIManager.put("Tree.collapsedIcon", new ImageIcon(ImageIO.read(getClass().getResource("/images/icons8-collapse-arrow-24.png"))));

                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() throws IOException {
            setLayout(new BorderLayout());
            JTree tree = new JTree();
            tree.setShowsRootHandles(true);

            List<Item> items = new ArrayList<>(8);
            items.add(new Item("Bowle",
                    new Item[]{
                        new Item("Apple"),
                        new Item("Pear"),
                        new Item("Orangle")
                    }));
            items.add(new Item("Freezer",
                    new Item[]{
                        new Item("Top draw", new Item[]{
                            new Item("Chicken"),
                            new Item("Steak"),
                            new Item("Fish")}),
                        new Item("Bottom draw", new Item[]{
                            new Item("Pears"),
                            new Item("Chips"),
                            new Item("Ice cream")})
                    }));

            DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("My stuff");
            for (Item item : items) {
                populate(rootNode, item);
            }
            DefaultTreeModel model = new DefaultTreeModel(rootNode);
            tree.setModel(model);
            tree.setCellRenderer(new ItemTreeCellRenderer());

            add(new JScrollPane(tree));
        }

        protected void populate(DefaultMutableTreeNode parent, Item item) {
            DefaultMutableTreeNode node = new DefaultMutableTreeNode(item);
            parent.add(node);

            for (Item child : item.getContents()) {
                populate(node, child);
            }
        }
    }

    class ItemTreeCellRenderer extends DefaultTreeCellRenderer {
        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
            if (value instanceof DefaultMutableTreeNode) {
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
                Object userValue = node.getUserObject();
                if (userValue instanceof Item) {
                    Item item = (Item) userValue;
                    value = item.getName();
                }
            }
            return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
        }
    }

    public class Item {
        private String name;
        private List<Item> contents;

        public Item(String name) {
            this.name = name;
            this.contents = new ArrayList<>(8);
        }

        public Item(String name, Item[] children) {
            this.name = name;
            this.contents = new ArrayList<>(Arrays.asList(children));
        }

        public String getName() {
            return name;
        }

        public List<Item> getContents() {
            return contents;
        }
    }
}

Upvotes: 1

Related Questions