简体   繁体   中英

Elegant way to accomplish realization in Java Swing?

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:

  1. draw dummy text to force realization
  2. get font metrics
  3. erase dummy text
  4. 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.

As discussed here , each Swing component has a UI delegate that calculates the correct preferred size for a component, given the user's chosen Look & Feel. As a result, the most elegant solution is to let the layout manager leverage the components's preferred size. Failing to do so often leads to his pathologic behavior . As shown here and here , you can validate() the enclosing container to obtain the desired geometry before setVisible() , but doing so is a sign that another approach may be warranted. As a concrete example, this BoxLayout example is better done using GroupLayout , illustrated here and here .

Typically, you should only need to examine FontMetrics in order to calculate the preferred size of your own custom components, as shown here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM