I'm trying to render a custom Swing component where I've extended the JComponent class.
For the purpose of simplifying the component requirements, lets just summarize my component as needing to render a few strings, each with their own fonts.
I need my component to be sized exactly to the summed width and height of my rendered strings.
In order to determine this size, I use the FontMetrics to calculate the dimensions of each string. Having this information I can figure out what size my component will be and resize it appropriately.
The problem is that when I access the getGraphics() it is always null, so I can't get the FontMetrics instance. If I wait to calculate my component size from the overriden paintComponent() method, its pretty much too late (the component already has a size, right?).
The documentation says that "This method will return null if this component is currently not displayable". So when do I know when the component is ready to be displayed and has a Graphics object for me to resize my component?
What is the Swing invokation order for rendering the component once the frame setVisible(true) is called?
Thanks
Update: Tuesday, Feb 06, 2010 at 23:34
As mentioned bellow in the comments, the GridLayout doesn't respect any setXxxSize() at all. For anyone interested, I've posted results of using the GridLayout, BoxLayout and FlowLayout using a simple frame that receives 5 fixed size components of 200 wide by 50 in height (by setting min, max and preferred).
Test Results:
The GridLayout is always resized along the width and height (as mentioned in comments)
The FlowLayout always respected the components size regardless.
As for the the BoxLayout...
The PAGE_AXIS and Y_AXIS shrank the width of the components to about half their size (104) but did not shrink the height.
The LINE_AXIS and X_AXIS shrank the height of the components to what seemed zero but did not touch the width.
First, you can measure your Strings using the TextLayout class and its associated stuff. For example
public static void main(final String[] args) throws Exception
{
final FontRenderContext frc = new FontRenderContext(null, true, true);
final Font font = new Font("serif", Font.PLAIN, 18);
final TextLayout layout = new TextLayout("This is a test", font, frc);
final Rectangle2D bounds = layout.getBounds();
System.err.println((int) (bounds.getWidth() + .5));
}
Secondly, you can be informed when your component has become visible by using a ComponentListener, but that's not necessary for measuring your strings in "advance"!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With