繁体   English   中英

为什么会收到此NullPointerException?

[英]Why am I getting this NullPointerException?

我不知道这个。 使用新的Canvas()初始化Canvas之后,对其进行引用将导致NullPointerException。 该文档告诉我,当“画布”未“启用”时会发生这种情况,但是我不知道启用它意味着什么。 我试图通过包括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()
    }
}

我已经有一段时间没有使用Swing了,但是尝试在调用get图形之前将画布添加到Panel中(该面板也应该具有某种形式的布局)。 您可以在此处找到一个有趣的教程: http : //docs.oracle.com/javase/tutorial/uiswing/ “要在屏幕上显示,每个GUI组件都必须是容器层次结构的一部分。容器层次结构是具有以下内容的组件树以顶级容器为根。我们将向您展示一个。” 因此,我认为实例化canvas类是不够的。 仅在将图形对象添加到顶层容器后,才将其分配给您的画布对象。

在组件无法显示之前,其图形将为空。 这是一个真正的麻烦,因为没有没有Graphics访问FontMetrics简便方法。

我知道几种解决方案:

如果只需要线条高度,则Font.getLineMetrics()就足够了。

Toolkit.getDefaultToolkit().getFontMetrics(Font)可以使用,但已弃用。

一个不建议使用但不必要的绕行解决方案是创建BufferedImage并获取其Graphics

编辑:

实际上,从1.5开始,您可以执行cvs.getFontMetrics(DEFAULT_FONT) 我不敢相信我以前从未注意到过!

您可能首先不应该使用Canvas。 这是一个旧的AWT类。 如果使用的是JFrame,则使用的是Swing。 如果要绘制某些东西:子类JComponent,请重写paintComponent,然后可以在其中放置绘图代码。 我的猜测是getGraphics()返回null,因为它没有附加到父级。 您可能必须等到以后才能访问Graphics对象,就像显示它一样。

您不是应该先将Canvas添加到JFrame吗?

cvs = new Canvas(); 
getContentPane().add(cvs); 

someObject.getGraphics()在构造函数中的风险很高。 在这种情况下,可能由于尚未显示。 我建议在col上使用惰性实例化。 只需编写一个getter来检查它是否已被分配:

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

这样,您应该在第一次需要它时就获得Graphics对象。 作为额外的保障,您可以检查分配是否成功,如果为空(即快速失败),则抛出未经检查的异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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