This post originated from an RSS feed registered with Java Buzz
by Danno Ferrin.
Original Post: JTree Woes (or why src.jar is a ture gift)
Feed Title: And They Shall Know Me By My Speling Errors
Feed URL: http://shemnon.com/speling/archives/cat_GUI.rdf
Feed Description: Danno Ferrin's Many Reasons he was a Comp Sci Major and not an English Major
Nothing is worse than inexplicable behavior. Obscure behavior is close, but decidedly better.
So I've got this bug in my GUI code relating to changing names in a JTree, basically the structure of the JTree stays the same but the length of one of the names of one of the nodes expands significantly at times. The problem is that the new text is not displayed! (or actually, only 4 pixes of the new text is displayed, for another obscure reason).
My natural inclination is to blame my own code, so I dig into the debugger and stop it durring a swing rendering of the tree (two moniters would sure be nice for this). The first rendeering is perfect. The preferred size on the second (larger) rendering is also perfect. WTF? So after a few failed attempts to move stuff around I think to look at the rendering Graphics object, and lo and behold the clip is set to the first rendering size! This has me really confused, becuse I never have to handle passing around the Graphics object and I have become used to trusting that the rigght clipping is set up (that's a magical black box labeled "Efficient dirty region rendering" in my world). So then I (properly) conclude the causal factor is outside my code. Too bad, 'cause I still have to fix it.
This is where I am truely thankful that Sun ships most of the Java code that comes with the JDK in src.zip. I can crack open the implementation classes and look around and find what the real culprit is: JTree is caching the preferred sizes of the tree nodes when it is drawing it, and it's called an optimization. When you are using straight GDM code on a 200Mhx Pentium MMX running Windows 95 I suppose that optimizations like that make sense, but that is, like, so last millenia.
The problem is that this is a faulty optimization, because it clearly isn't keeping up to date or allowing for a hook to change the size of the widgets. Fourtionlatly my diging around also gives me anoter clue: when JTree.setLargeModel is set to true these cachings are ignored. I've always wondered what that property did! But the documentation is so... vauge. It was a real.... bummer. Six hours of head scratching work and the A-Ha moment comes and all I have to show for it is one measaly line of code.
There is still one last mystery in this though: this fix requires largeModel to be true and for rowHeight to be set to a non-zero value. Using the Windows Look And Feel sets this row height automatically, but not for Swing, and for the life of me I cannot find that code in the Windows Look and Feel code. So I just set the value to a previously rendered value when I am done with my data load thread, and it's all good on Linux. So a total of three lines changed (the second change was quite long, and I had to wrap it onto the next line).