Почему я получаю это исключение NullPointerException? - PullRequest
1 голос
/ 26 января 2012

Я не могу понять это.После инициализации Canvas с новым Canvas (), ссылка на него приводит к исключению NullPointerException.Документ говорит мне, что это может произойти, когда Canvas не «включен», но я не знаю, что значит быть включеннымЯ попытался отладить его, добавив while (! Cvs.isEnabled ());но программа просто зависла.Какие условия могут привести к отключению Canvas, и как их исправить?

Exception in thread "main" java.lang.NullPointerException
    at matt.io.ConsoleCanvas.<init>(ConsoleCanvas.java:72)
    at matt.io.ConsoleCanvas.<init>(ConsoleCanvas.java:51)
    at matt.io.ConsoleCanvas.main(ConsoleCanvas.java:32)

public class ConsoleCanvas extends JFrame
{
    private static final Font DEFAULT_FONT = new Font("Monospaced", Font.PLAIN, 12);
    public static void main(String[] args)
    {
        ConsoleCanvas me = new ConsoleCanvas(); //ConsoleCanvas.java:32
        //Program has crashed by this point, so rest of main removed to be concise
    }

    protected JTextField in;
    private Canvas cvs;
    private int row;
    private int col;

    public ConsoleCanvas()
    {
        this("Console Pane", 80, 10); //ConsoleCanvas.java:51
    }

    public ConsoleCanvas(String title, int rows, int cols)
    {
        in = new JTextField();
        in.setEditable(true);
        in.setFont(DEFAULT_FONT);
        in.setColumns(cols);

        cvs = new Canvas();
        cvs.setSize(in.getWidth(), in.getHeight() * rows);
        cvs.setFont(DEFAULT_FONT);
        row = 0;
        col = cvs.getGraphics().getFontMetrics().getHeight(); //ConsoleCanvas.java:72
        //Program crashes at this line, so I'll leave out the rest for brevity again
        //I've isolated the null to the Graphics returned by cvs.getGraphics()
    }
}

Ответы [ 5 ]

4 голосов
/ 26 января 2012

Я довольно долго не работал с Swing, но попробуйте добавить холст в Panel перед вызовом get graphics (панель также должна иметь некоторую форму компоновки). Вы можете найти интересное руководство здесь: http://docs.oracle.com/javase/tutorial/uiswing/ «Чтобы отображаться на экране, каждый компонент графического интерфейса должен быть частью иерархии содержимого. Иерархия содержимого - это дерево компонентов, корневым контейнером которого является контейнер верхнего уровня. Мы покажем вам один за другим». Поэтому я думаю, что создание экземпляра класса canvas недостаточно. Графический объект назначается вашему объекту canvas только после добавления его в контейнер верхнего уровня.

2 голосов
/ 26 января 2012

Пока компонент не отображается, его графика будет нулевой. Это настоящая проблема, потому что нет простого способа получить доступ к FontMetrics без Graphics.

Я знаю несколько решений:

Если вы просто хотите высоту строки, достаточно Font.getLineMetrics().

Toolkit.getDefaultToolkit().getFontMetrics(Font) работает, но не рекомендуется.

Не осуждаемое, но ненужное обходное решение - создать BufferedImage и получить его Graphics.

Edit:

На самом деле, с 1.5 вы можете просто сделать cvs.getFontMetrics(DEFAULT_FONT). Я не могу поверить, я никогда не замечал этого раньше!

1 голос
/ 26 января 2012

Вы, вероятно, сначала не должны использовать Canvas.Это старый класс AWT.Если вы используете JFrame, то вы используете Swing.Если вы хотите что-то нарисовать: создайте подкласс JComponent, переопределите paintComponent, и вы можете поместить туда свой код для рисования.Я предполагаю, что getGraphics () возвращает ноль, потому что он не привязан к родителю.Возможно, вам придется подождать до позднего времени, чтобы получить доступ к графическому объекту, как после его отображения.

0 голосов
/ 26 января 2012

someObject.getGraphics () общеизвестно рискованно в конструкторе.В этом случае, вероятно, так как он еще не отображался.Я бы порекомендовал использовать ленивый экземпляр на col.Просто напишите геттер, который проверяет, назначен ли он еще:

public Graphics getCol() {
    if (col == null) {
        col = cvs.getGraphics();
    }
    return col;
}  

Таким образом, вы должны получить объект Graphics в тот момент, когда он вам понадобится впервые.В качестве дополнительной меры безопасности вы можете проверить, было ли назначение успешным, и сгенерировать непроверенное исключение, если оно пустое (т. Е. Устойчивое к сбоям).

0 голосов
/ 26 января 2012

Разве вы не должны сначала добавить Canvas в JFrame?

cvs = new Canvas(); 
getContentPane().add(cvs); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...