How to colorize JTree and all nodes

Let me explain what I need and how far I have come:

I have a JTree with a user model and some nice icons, and everything works as it should, however the default colors of the tree (white) do not fit into the GUI I'm trying to create, and I'd like to be able to change my color background.

This turned out to be quite a challenge!

I saw a lot of explanations about this on the net, and they seem to revolve around either the DefaultTreeCellRenderer extension or BasicTreeUI , but there is speculation that these are hacks and should be avoided, although there is little explain why they are hacks or what should be done instead .

In any case, none of the suggested methods works very well, because I always get one of two scenarios:

The color is set in the tree, but there are unpleasant gaps between the tree labels and the right side of the tree, as well as between the labels and their icons, as well as plus / minus widgets for expanding the tree. In this case, it is proposed to implement a complete selection of strings.

In another scenario, a complete selection of rows is implemented, and the nodes are correctly colored and a complete selection of rows is performed, but the icons are either completely absent, plus / minus widgets, or there is a white border around both.

My own attempts at this have failed, and for the time being I am leaving the following code that paints the tree and the nodes, but still leaves an unpleasant white border at the end of the tree labels and between all the icons.

 final Color MainBg = new Color(213,220,228); KTree.setCellRenderer(new DefaultTreeCellRenderer() { @Override public Component getTreeCellRendererComponent(JTree pTree, Object pValue, boolean pIsSelected, boolean pIsExpanded, boolean pIsLeaf, int pRow, boolean pHasFocus) { super.getTreeCellRendererComponent(pTree, pValue, pIsSelected, pIsExpanded, pIsLeaf, pRow, pHasFocus); setBackgroundNonSelectionColor(MainBg); setBackgroundSelectionColor(MainBg); setTextNonSelectionColor(Color.BLACK); setTextSelectionColor(Color.BLACK); ImageIcon tDoc = createImageIcon("images" + File.separator + "document.gif","document"); ImageIcon tOpen = createImageIcon("images" + File.separator + "book_open.gif","book open"); ImageIcon tClosed = createImageIcon("images" + File.separator + "bookclosed.png","book closed"); setClosedIcon(tClosed); setOpenIcon(tOpen); setLeafIcon(tDoc); putClientProperty("Tree.collapsedIcon", tDoc); putClientProperty("tree.expandedIcon", tOpen); return (this); } }); 

My question (s):

1) Naturally, I would appreciate help in getting the JTree color set, and I am open to suggestions, although if you plan to publish a link, there is a good chance that I have already been there in the last few days, but also ...

2) Id appreciate the final explanation of what exactly is involved in this process. Iv read a lot of JTree , but none of them focused for a long time (if at all) on the question of the full coloring of the tree, and this is what I am looking for, and there seems to be some discussion about what exactly is required, for example full row selection or not, subclassification or not, etc.

I would also like to understand why some things are considered “hacks” and which alternatives.


EDIT - solution

I am adding this section to show my progress in sorting this out and possibly letting others start a little, which was a rather complicated process. Iv spent days trying to get this to work properly with System L & F, and I have been in circles several times. Without a doubt, a lot of this depends on inexperience, so if it saves someone a few more sessions of hair extension, all the better!

BTW: I'm more than happy to hear criticism if I did something that is considered a hack, but please provide a (working) alternative and some clear reasoning behind the Hack brand.

Ok, let's get started: I want to install the L & F system because I don’t like the other options too much, and because I like users to see a program that matches the things they are used to. I installed L&F like this before I do anything else:

 try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { return; } 

This sets the JTree value to standard for any operating system that you use. This, apparently, includes setting the background of the tree itself, as well as the background for selecting the node, and so on. Are you ready to go if all you need is a standard JTree , but for now I want to see scrollbars based on the system, etc., I also want to see colors other than white for the background.

I set the background to blue this way (note that the color is used again in a moment, hence the final declaration):

 final Color MainBg = new Color(213,220,228); KTree.setBackground(MainBg); 

Now I have a JTree with a nice blue background that only covers areas of the tree that do not contain nodes that remain white according to the L & F settings. Now I need to set the color in the nodes themselves, and for this I need to override getTreeCellRendererComponent DefaultTreeCellRenderer following code:

 final Color SellBg = new Color(232,235,237); final Color HiliBg = new Color(150,196,246); KTree.setCellRenderer(new DefaultTreeCellRenderer() { @Override 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); setBackgroundNonSelectionColor(MainBg); setBackgroundSelectionColor(SellBg); setTextNonSelectionColor(Color.BLACK); setTextSelectionColor(Color.BLACK); ImageIcon tDoc = createImageIcon("images" + File.separator + "document.gif","document"); ImageIcon tOpen = createImageIcon("images" + File.separator + "book_open.gif","open"); ImageIcon tClosed = createImageIcon("images" + File.separator + "bookclosed.png","closed"); setClosedIcon(tClosed); setOpenIcon(tOpen); setLeafIcon(tDoc); setBorderSelectionColor(HiliBg); return this; } }); 

The following is a description of createImageIcon. This came directly from the tutorial, but note that this is being edited until I finished with it (so don't copy and paste this code!):

 protected ImageIcon createImageIcon(String path, String description) { java.net.URL imgURL = getClass().getResource(path); if (imgURL != null) { return new ImageIcon(imgURL, description); } else { System.err.println("Couldn't find file: " + path); return null; } } 

If you follow the code, then at this point you will see that I have set different colors for the tree nodes and also added some icons to them. All this works very well, but now there are nasty white blocks between the ends of the node text and the edge of the JTree itself, as well as between the text and the node icon and the plus / minus tree widgets. These white blocks also pass through the tree as it expands.

This is pretty much where I went in and the hair movement started. Thanks to Jacob’s suggestion and MadProgrammer’s hint (thanks guys), I was on the right track, but everything is strange here, most likely because I was already messing around with JTree to try and get everything working. Repeating the code back to the previous version and beginning of this section again helped to succeed.

Quick note: Please, if I do it wrong, let me know!

It seems that to change the white parts of JTree I would need to override the BasicTreeUI , which I liked:

 KTree.setUI(new javax.swing.plaf.basic.BasicTreeUI() { @Override public Rectangle getPathBounds(JTree tree, TreePath path) { if(tree != null && treeState != null) { return getPathBounds(path, tree.getInsets(), new Rectangle()); } return null; } private Rectangle getPathBounds(TreePath path, Insets insets, Rectangle bounds) { bounds = treeState.getBounds(path, bounds); if(bounds != null) { bounds.width = tree.getWidth(); bounds.y += insets.top; } return bounds; } }); 

I have to say that this is not my code. I found this on one of many tutorial sites, and it worked as suggested, and my JTree now had a properly colored background, however the plus / minus widgets disappeared!

Most likely, this is an easy way to install these widgets from the above code, however, I remembered Jacob's warning about messing with BasicTreeUI , so I placed the following code immediately after installing L & F:

 ImageIcon clapsed = createImageIcon("images" + File.separator + "plus.gif","closed"); ImageIcon clopen = createImageIcon("images" + File.separator + "minus.gif","open"); UIManager.getLookAndFeelDefaults().put("Tree.collapsedIcon",clapsed); UIManager.getLookAndFeelDefaults().put("Tree.expandedIcon",clopen); UIManager.getLookAndFeelDefaults().put("Tree.paintLines", true); UIManager.getLookAndFeelDefaults().put("Tree.leftChildIndent",7); UIManager.getLookAndFeelDefaults().put("Tree.lineTypeDashed",true) 

This sets the widget icons plus / minus for my own and sets the type of colored rows that I want between the elements in the tree. Please note that at this moment I received an error because the non-static createImageIcon from previously could not be accessed. I had to edit code like this to allow both calls to this method:

 protected static ImageIcon createImageIcon(String path, String description) { Class<?> cl=new Object(){}.getClass().getEnclosingClass(); java.net.URL imgURL = cl.getResource(path); if (imgURL != null) { return new ImageIcon(imgURL, description); } else { System.err.println("Couldn't find file: " + path); return null; } } 

Now I (finally!) JTree with a set of System L & F and with a set of colors for all elements of the tree.

There are still unresolved issues:

I haven't figured out the BasicTreeUI() code BasicTreeUI() - it gave me the colors I needed, but it seemed to give me a complete selection of strings. However, I was not able to get the highlight color to cover the entire distance. I intend to play with this later, but I will be careful thanks to a warning from Jacob. If anyone has any hard and fast rules regarding this, I am more than happy to hear them.

I also intentionally install L & F so that users can see something familiar, albeit with different colors. However, I was forced to add my own icons to the plus / minus widgets, which is actually not a problem, but rather a little annoyance. This can be clarified later.

My other problem is that when setting values ​​using UIManager I can only set certain keys, others are apparently ignored. MadProgrammer really noted that using Nimbus can spoil these keys a bit, so perhaps using the L & F system has its own features.

In any case, this is the current result of my efforts. I apologize for the length of this post, but I hope this can help someone else, and also, if I did something wrong, someone can point me to the right path.

Hi

MVK

+4
source share
2 answers

If you have already redefined getTreeCellRendererComponent so that the tree elements have the desired color, you can use

 UIManager.getLookAndFeelDefaults().put("Tree.background", new ColorUIResource(aColor); 

to change the color of the "unoccupied" space in the tree. Please note that this will affect all future trees. UI component classes use this property and many, for example, when drawing their components. To find out which keys exist, you can do something like this:

 for (Entry<Object, Object> entry : UIManager.getLookAndFeelDefaults().entrySet()) { System.out.println(entry.getKey() + " : " + entry.getValue()); } 

As for your other questions, I would never have thought of redefining getTreeCellRendererComponent as a hack, but a careless extension of BasicTreeUI may lead to unexpected behavior with some looks and sensations.

+3
source

If all you are looking for is a way to have both System L & F and color background + text in JTree, this is all you need:

  try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); UIManager.getLookAndFeelDefaults().put("Tree.background", new ColorUIResource(Util.BACKGROUND)); UIManager.getLookAndFeelDefaults().put("Tree.textBackground", new ColorUIResource(Util.BACKGROUND)); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) { e.printStackTrace(); } 
0
source

All Articles