Reputation: 9042
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.
Upvotes: 6
Views: 3007
Reputation: 324118
Use a JLabel for rendering your Strings then you can just use the getPreferredSize() method of thel label.
Upvotes: 2
Reputation: 45324
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"!
Upvotes: 7