簡體   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