Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When will getGraphics() return a valid graphics instance?

Tags:

java

swing

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.

like image 290
Jeach Avatar asked Feb 16 '10 18:02

Jeach


1 Answers

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"!

like image 173
Jonathan Feinberg Avatar answered Nov 06 '22 22:11

Jonathan Feinberg