As many of you may well be aware (since I’ve mentioned it a lot), I’m trying to build a JPanel that resizes its text whenever the panel itself is resized, so that the text always takes up the maximum space it can. I’ve struggled with this a lot, and I think I’m the closest I’ve come to date to having a solution.
But I’m having one big problem. First, let me give you my code. The comments should explain most of it, but there’s two variables that are unexplained. “allTexts” is an array of Strings that holds all the lines of text that will be used for the panel (my approach only tests for line width, not height), and “allFonts” is an array of Fonts that holds all the fonts used by all the texts.
Here’s my code:
// Setting the fontSize. First we find the longest line. We create an integer to specify the longest line:
int longestLine = 0 ;
// We'll need a FontRenderContext to get widths with:
FontRenderContext fontRC = g2D.getFontRenderContext () ;
// Now we count through the lines:
for ( int i = 1 ; i < allTexts.length ; i ++ ) {
// Is the current line longer than the longest line?
if ( allFonts [ i ].getStringBounds ( allTexts [ i ] , fontRC )
.getWidth ()
> allFonts [ longestLine ]
.getStringBounds ( allTexts [ longestLine ] , fontRC )
.getWidth () )
// If so, set a new longestLine:
longestLine = i ;
}
// Setting maxFont and maxWidth, using longestLine:
Font maxFont = allFonts [ longestLine ] ;
String maxWidth = allTexts [ longestLine ] ;
// the ratio of the longest line's point size to its width, so that we can
// make a ballpark guess as to the right font size:
float widthRatio = maxFont.getSize2D ()
/ ( float ) maxFont.getStringBounds ( maxWidth, fontRC ).getWidth () ;
// Now using that ratio to make a ballpark guess as to the font size:
fontSize = getWidth () * widthRatio ;
// Setting maxFont to that size:
maxFont = maxFont.deriveFont ( fontSize ) ;
// Is the maxWidth string smaller than the width of the panel by more than 3
// pixels?
while ( getWidth () - maxFont.getStringBounds ( maxWidth, fontRC ).getWidth ()
> 3 ) {
// If so, increase the size of the font by half a point:
fontSize = fontSize + 0.5f ;
maxFont = maxFont.deriveFont ( fontSize ) ;
// Is the maxWidth String now longer than the width of the panel?
if ( getWidth () < maxFont.getStringBounds ( maxWidth, fontRC ).getWidth () )
// If so, break out of the loop:
break ;
}
// Is the maxWidth String now longer than the width of the panel?
while ( getWidth ()
< maxFont.getStringBounds ( maxWidth, fontRC ).getWidth () ) {
// If so, decrease the size of the font by half a point:
fontSize = fontSize - 0.5f ;
maxFont = maxFont.deriveFont ( fontSize ) ;
}
// Now we should have maxFont at the largest size possible, within half a point.
So, this all seems to work, with one problem: the lines come out too short. I realize my code allows the lines to be up to 3 pixels shorter than the width of the panel, but the lines come out way shorter than that. The longest line of text seems to be 8-12 pixels short of the side of the panel. I tried setting my code to be more sensitive, by changing the "0.5f"s to "0.05f"s, but it didn’t seem to change the size the lines were coming out. Can anyone see what’s going on ?
