Once more I have battled with Java’s idiocy. As usual, the problem lies with Swing, the graphics system that automatically lays out window elements for you in a supposedly intelligent manner that automatically adjusts for changes in window size. The concept of Swing is nice, but when it doesn’t even properly lay out the window for a fixed size, I get hot under the collar.
My desire is to line up labels with rectangles, like so:
(Ignore the rectangle bounding the labels; it’s for diagnostic purposes.) The labels must move around as the colored rectangles are resized, like so:
I organized this as two vertically stacked JPanels, each containing the five basic elements (five colored boxes in the upper, five colored labels in the lower.) Perhaps I should have organized it as a single JPanel containing five JPanels, each a vertical stack consisting of a colored rectangle and a label. However, this would have raised tricky problems with the thumbs that separate the colored rectangles. Moreover, it should work just as well in either vertical or horizontal layout.
The problem was to figure out the size of the spacer elements between each label and then place them. Trivial, one would think. One would think. First, I tried using space characters -- I figured that would be simple. But no: apparently Swing compresses space characters as part of its squeezing things in to fit, so that space characters do not provide a computable means of spacing the labels.
OK, so I went to the more conventional approach of inserting Horizontal Struts. That created a real mess; for some reason, when horizontal struts are inserted between labels, they demand infinite vertical space, squeezing the colored boxes out of existence. Why do they do that? Who knows, it’s Java.
A sufficiency of cussing eventually brought me to the next solution: use Rigid Areas rather than Horizontal Struts. A Rigid Area is simple the combination of a Vertical Strut and a Horizontal Strut; it covers a fixed area, rather than a fixed horizontal or vertical length. Why did I need a Rigid Area to perform the function of a Horizontal Strut? Who knows, it’s Java. Anyway, once I replaced the Horizontal Struts with Rigid Areas (with a defined vertical extent), the screen started looking a little better.
However, Java still isn’t done toying with me. Now the problem is initialization. When I first draw the screen, it looks like this:
Note the several screw-ups. First, the thing expands to use lots more horizontal space, even though it doesn’t use it. That vertical grey line on the right side of the window should be much further to the left. But no, Java insists on hogging lots of space that it doesn’t bother using. Second, note how only THREE of the labels are displayed. Apparently Java wants all that extra space for the two other labels, but it refuses to display them. Sure, it makes no sense; it’s Java.
It gets better. Take that first thumb from the left. If I click and drag it ever so slightly, the display jumps to this:
OK, now at least we have all five labels in place. But the damn thing still insists on hogging space that it refuses to use. However, when I drag that thumb just a little bit further, I get this:
Ta-da! Java arbitrarily decided to stop being a space hog and shrank that JPanel to its proper size. But NOW it has a new trick: it repositions the thumb to the same location relative to the window, not relative to the panel, so that I have, in effect, dragged the thumb far to the right, squeezing the green rectangle out of existence. Why does it do that? Because it’s Java, of course!
So I shall spend today unravelling the deranged mind of Java and figuring out how to fool it into sane behavior. This is just one more reason why I hate Java.
I have struggled through all sorts of experiments and determined that the problem arises from the fact that the rectangles and labels must actually be drawn on the screen in order for Java to figure out what’s going on. Of course, they’re drawn incorrectly at first, but something about drawing them once gets the basic elements in place, and the second drawing is right on the money. I have therefore implemented a simple fix, which is a true kluge: at game initialization, I draw each of the offending pages with no delays between the drawings. Then I draw the page that the player will begin with. The player sees some pages flash on the screen, and then the starting page. Now everything works just fine. But why does Java require the images to be actually drawn in order to correctly calculate their sizes? We all know the answer: it’s just Java.