2012-01-26 8 views
1

나는 이것을 이해할 수 없다. 새 Canvas()로 Canvas를 초기화 한 후이를 참조하면 NullPointerException이 발생합니다. 이 문서는 캔버스가 "활성화"되어 있지 않을 때 발생할 수 있다고 알려주지 만 활성화 할 수 있다는 것이 무엇인지 모릅니다. while (! cvs.isEnabled());을 포함 시켜서 디버깅하려고했습니다. 그러나 프로그램은 단지 매달렸다. Canvas가 활성화되지 않을 수있는 조건은 무엇이며 어떻게 수정할 수 있습니까?왜이 NullPointerException이 발생합니까?

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() 
    } 
} 
+2

"cvs.getGraphics(). getFontMetrics(). getHeight();"에있는 getter 중 하나입니다. null을 반환합니다 –

+0

격리되었습니다. 'Graphics graphics = cvs.getGraphics(); if (graphics == null) System.out.println ("graphics"); –

+0

getGraphics를 사용하지 마십시오. 커스텀 페인팅을하고 싶다고 가정하면 (Swing에서) paintComponent를 오버라이드하는 것입니다. – kleopatra

답변

4

꽤 오랫동안 스윙을 사용하지 못했지만 그래픽을 가져 오기 전에 패널에 캔바스를 추가 해보십시오 (패널에 레이아웃이 있어야합니다). 재미있는 자습서는 http://docs.oracle.com/javase/tutorial/uiswing/ "화면에 표시하려면 모든 GUI 구성 요소가 포함 계층 구조의 일부 여야합니다. 포함 계층 구조는 최상위 컨테이너가 루트 인 구성 요소의 트리입니다. 당신은 조금 있습니다. " 그래서 저는 캔버스 클래스를 인스턴스화하는 것으로 충분하지 않다고 생각합니다. 그래픽 객체는 최상위 컨테이너에 추가 한 후에 만 ​​캔버스 객체에 할당됩니다.

+0

이미 JScrollPane을 준비 했으므로 코드에 추가했습니다. 그것을 10 줄 위로 움직이면 NPE가 고정되었습니다! 감사! 이제 문제는 Canvas의 높이가 0이지만, 저는 그것에 대해 독자적으로 연구 할 것입니다. –

2

구성 요소를 표시 할 수있을 때까지 그 그래픽은 null이됩니다. Graphics없이 FontMetrics에 액세스하는 쉬운 방법이 없기 때문에 이것은 진정한 번거 로움입니다. Font.getLineMetrics() 충분, 당신은 단지 행 높이를 원하는 경우

:

는 내가 알고있는 몇 가지 솔루션을있다.

Toolkit.getDefaultToolkit().getFontMetrics(Font)은 작동하지만 더 이상 사용되지 않습니다.

비 필수이지만 꼭 필요하지 않은 원형 교차 솔루션은 BufferedImage을 만들고 Graphics을 얻는 것입니다.

편집 :

사실, 1.5로 그냥 cvs.getFontMetrics(DEFAULT_FONT) 할 수 있습니다. 나는 결코 전에 그것을 알아 채지 않았다라고 생각할 수 없다!

1

아마도 Canvas를 사용하지 않아야합니다. 이것은 오래된 AWT 클래스입니다. JFrame을 사용하고 있다면 스윙을 사용하고있는 것입니다. 무언가를 그리는 경우 : JComponent을 서브 클래스 화하고 paintComponent를 오버라이드하면 그리기 코드를 그곳에 배치 할 수 있습니다. 내 생각 엔 getGraphics()는 부모에게 연결되어 있지 않기 때문에 null을 반환합니다. 나중에 나타날 때까지 그래픽 객체에 액세스 할 때까지 기다려야 할 수도 있습니다.

+0

Drat를 반환하십시오. 저는 Canvas에서 정말 필요한 것은 drawString (String) 메서드이며, 저는 스스로 혼자서 기능을 수행하는 방법을 가장 안 좋은 것으로 생각합니다. –

+0

@Matt G Canvas에는 drawString 메서드가 없습니다. 아마 당신은 Graphics 객체로부터 그 메소드를 원할 것입니다. 자습서를 참조하십시오. http://docs.oracle.com/javase/tutorial/uiswing/painting/ –

+0

drawString()은 paintComponent()를 서브 클래 싱하고 오버라이드 할 때와 동일한 그래픽의 인스턴스 메소드입니다. getPreferredSize()에서 크기를 계산할 수 있습니다. – chubbsondubs

0

먼저 JFrame에 캔버스를 추가해야합니까?

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

someObject.getGraphics()는 생성자 내에서 악명이 높습니다. 이 경우 아직 표시되지 않았기 때문에 가능합니다. 나는 칼에 게으른 인스턴스를 사용하는 것이 좋습니다거야.

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

그런 식으로, 처음으로 필요한 순간에 Graphics 객체를 가져와야합니다. 추가 안전 장치로 할당이 성공했는지 여부를 확인할 수 있으며 널 (null) (즉, 페일 패스트) 인 경우 검사되지 않은 예외를 throw합니다.

관련 문제