3

Part of a GUI I'm creating for a bookkeeping program in Java needs to display a varied String. Before displaying this String, it must add line breaks where appropriate. To do this, I've created a class which extends JTextArea, and overridden the setText() method as such:

public class ContentPane extends JTextArea {

private FontMetrics fm;

public ContentPane() {
    super();
    // Instatiate FontMetrics
}

public ContentPane(String string) {
    super(string);
    // Instatiate FontMetrics
}

@Override
public void setText(String text) {
    int n;
    String remainder;

    while (fm.stringWidth(text) > maxStringWidth()) {
        n = numberOfCharsToCut(text);
        remainder = text.substring(text.length() - n);
        text = text.substring(0, text.length() - n) + "\n" + remainder;
    }

    super.setText(text);
}

private int numberOfCharsToCut(String str) {
    String newStr = str;
    int i = 0;
    while (fm.stringWidth(newStr) > maxStringWidth()) {
        newStr = str.substring(0, str.length() - i);
        i++;
    }
    return i;
}

private int maxStringWidth() {
    return fm.stringWidth("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@lll");
}
}

In place of "// Instatiate FontMetrics", I've tried a few different things. At first I tried to create a FontMetrics object using "new"...

fm = new FontMetrics();

...only to find you can't instantiate FontMetrics in such a way. I tried retrieving a FontMetrics object using getFontMetrics(font), getting the default swing font from an answer in this question:

How do I get the default font for Swing JTabbedPane labels?

My code looked like this:

fm = getFontMetrics(UIManager.getDefaults().getFont("TabbedPane.font"));

This threw a NullPointerException. I also tried:

fm = getGraphics().getFontMetrics(UIManager.getDefaults().getFont("TabbedPane.font"));

This gave me a NullPointerException as well. Perhaps I'm not understanding how to use FontMetrics. Any insight is well appreciated.

Edit: Alright, now I've additionally tried the two above snippets again, replacing UIManager.getDefaults().getFont(...) with getFont(). The same NullPointerException is thrown.

Community
  • 1
  • 1
sleeparrow
  • 1,242
  • 13
  • 22
  • DO NOT EVER use getGraphics()! This will return NULL if the component had not been painted yet. It is possible that the UI defaults haven't been loaded when you start making your calls. – MadProgrammer Mar 13 '13 at 07:22
  • @MadProgrammer Never in this case, or never ever? – sleeparrow Mar 13 '13 at 08:21
  • This is a difficult question to answer as it's out of context. `getGraphics` provides you with a copy of the last graphics context that was used to render the component. This will be null if the component has never been renderered to the screen. It is a bad practice to rely on or generally use this method. So while "never" might be a little harsh, it should generally be avoided. – MadProgrammer Mar 13 '13 at 08:29

1 Answers1

0

To determine what the problem is, you should try to separate out each of the logical lines in the physical line that is throwing the exception. For example,

UIDefaults uiDefaults = UIManager.getDefaults();
Font font = uiDefaults.getFont("TabbedPane.font");
Graphics graphics = getGraphics();
fm = graphics.getFontMetrics(font);

I would suspect that the problem is that there is not a font registered with the "TabbedPane.font" key in the UI defaults. To overcome that, you should be able to get the font directly from your component via the Component#getFont method. That is really the font that you want anyway.

Matthew T. Staebler
  • 4,756
  • 19
  • 21