I often have the problem that a Swing method or property requires the object to be realized. For example, to draw on a JPanel I may need to know how tall a particular font is, but this information is not available until after the panel is realized, so I will get a null pointer before that. To make matters worse it is not always clear (to me at least) which methods require the object to be realized and which do not.
Obviously I can do something stupid like:
- draw dummy text to force realization
- get font metrics
- erase dummy text
- calculate and draw real text
It seems incredibly harebrained to have to do this. Is there a more elegant way to force realization so I can get reliable access to the font metrics?
Typical example code:
void draw( Point2D center ){
String sLabel = owner.getLabel();
NodeData.DATA_TYPE eType = owner.data_type;
int iSymbolWidth = 10;
// build text
if( sLabel == null ) sLabel = "";
Font font = new Font( "TimesRoman", Font.PLAIN, 12 );
text_node.setTextPaint( Color.DARK_GRAY );
text_node.setText( sLabel );
text_node.setFont( font );
Panel_Main panel = owner.application.getDisplayPanel();
java.awt.FontMetrics fm = panel.canvas.getGraphics().getFontMetrics(); // <--- ERROR HERE
int iText_AdvanceWidth = ( int ) ( fm.stringWidth( sLabel ) * 1.2 ) + LABEL_MARGIN * 2;
int iText_Height = fm.getHeight();
.... etc
Part of the problem is that the object I am drawing on is owned by Piccolo, a graph drawing library, so the library owns paintComponent, not me. On digging through the Piccolo source code, it appears I need to override one of their internal methods, paint(PPaintContext paintContext), which basically should be equivalent to overriding paintComponent.