2012-10-24 2 views
3

스퀘어 위에 그리드를 그려야하는 스윙을 사용하여 Java 응용 프로그램을 작성했습니다. 이렇게하려면 Graphics 클래스에서 제공하는 drawLine(...) 메서드를 사용하고 있습니다.Java Swing : drawLine very slow

모든 작업은 각 행을 그리는 데 많은 시간이 필요하다는 점을 제외하고는 모두 잘 작동합니다 (50 줄의 경우 20 초 이상 ...). 실시간으로 그려지는 선들도 볼 수 있습니다. 하나의 이상한 것은 수평선이 수직선보다 빨리 그려진다는 것입니다 (거의 즉시).

나는 뭔가 잘못하고있을 수도 있습니다. 여기 그리드에 대한 코드가 있습니다.

public void drawGrid(Graphics g){ 
    g.setColor(new Color(255, 255, 255, 20)); 
    int width = getWidth(); 
    int height = (int) (width * Utils.PLATE_RATIO); 
    int step = pixelSize*gridSpacing; 
    Color bright = new Color(255, 255, 255, 100); 
    Color transparent = new Color(255, 255, 255, 20); 
    for(int ix = insets.left + step;       
      ix < width; ix += step){ 
     if(((ix - insets.left)/step) % 10 == 0){ 
      g.setColor(bright); 
     } 
     else{ 
      g.setColor(transparent); 
     } 
     g.drawLine(ix, insets.top, ix, height+insets.top); 
    } 
    for(int iy = insets.top+step; 
      iy < (insets.top + height); iy += step){ 
     if(((iy - insets.top)/step) % 10 == 0){ 
      g.setColor(bright); 
     } 
     else{ 
      g.setColor(transparent); 
     } 
     g.drawLine(insets.left, iy, width + insets.left, iy); 
    } 
} 
+5

이중 버퍼링을 사용하지 않기 때문입니다. http://docs.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html –

+0

을 참조하십시오. 물론, 어떻게 그렇게 어리 석을 수 있습니까? 고맙습니다 ! – Nicolas

+3

@SureshKumar 스윙 구성 요소는 기본적으로 더블 버퍼링입니다 ... – kleopatra

답변

4

게시 한 코드는 문제가 없으며 아무 문제가 없습니다. 나는 코드의 조각 밖에서 문제가있는 것 같다

public static class MyGrid extends JComponent 
{ 
    private int step = 10; 

    public MyGrid() 
    { 
     super(); 
    } 

    public Dimension getPreferredSize() 
    { 
     return new Dimension (500, 500); 
    } 

    protected void paintComponent (Graphics g) 
    { 
     super.paintComponent (g); 
     drawGrid (g); 
    } 

    public void drawGrid (Graphics g) 
    { 
     int width = getWidth(); 
     int height = getHeight(); 
     Color bright = new Color (255, 255, 255, 200); 
     Color transparent = new Color (255, 255, 255, 100); 

     for (int ix = step; ix < width; ix += step) 
     { 
      if ((ix/step) % 10 == 0) 
      { 
       g.setColor (bright); 
      } 
      else 
      { 
       g.setColor (transparent); 
      } 
      g.drawLine (ix, 0, ix, height); 
     } 

     for (int iy = step; iy < height; iy += step) 
     { 
      if ((iy/step) % 10 == 0) 
      { 
       g.setColor (bright); 
      } 
      else 
      { 
       g.setColor (transparent); 
      } 
      g.drawLine (0, iy, width, iy); 
     } 
    } 
} 

: 여기
는 방법 (간단한 비트)를 사용하여 구성 요소의 작동 예입니다.

P. 조금만 그렇지만 ...

그림 영역의 보이는 부분 (JComponent의 getVisibleRect() 메서드 또는 Graphics g.getClip().getBounds() 메서드 사용)을 계산하고 해당 영역 만 사용하여 그림을 제한하는 것이 좋습니다.

이렇게 작은 최적화를 사용하면 구성 요소의 그림이 실제로 큰 경우 (예 : 10000x10000 픽셀 구성 요소 영역 포함) 구성 요소의 페인팅 속도가 빨라질 수 있습니다.

+1

getVisibleRect() +1 – mKorbel

+0

코드 외부에 문제가 있다고 생각하지 않습니다. 나는 당신과 거의 같았습니다. 이제 getWidth()를 getVisibleRect(). getSize()로 대체했습니다. 아래 내 솔루션을 참조하십시오. – Nicolas

-1

@sureshKumar의 권고에 따라 Double-Buffering을 사용하여 문제를 해결 한 방법은 다음과 같습니다. 나는 단순히 오프 스크린 이미지를 그리기 만하고 도면이 끝나면 drawImage()을 호출하기 만하면됩니다. 이것은 트릭을 할 것으로 보인다.

편집 :이 당신이 paintComponent(...) 방법의 외부에서 (내 경우 drawGrid()에) 당신의 그림 메소드를 호출 할 경우에만 유용 할 것으로 보인다. 여기

코드입니다 :

private Graphics bufferGraphics; 
private Image offScreen; 
private Dimension dim; 
//other attributes not shown... 

public CentralPanel(){ 
    //Some initialization... (not shown) 

    //I added this listener so that the size of my rectangle 
    //and of my grid changes with the frame size 
    this.addComponentListener(new ComponentListener() { 

     @Override 
     public void componentResized(ComponentEvent e) { 
      dim = getVisibleRect().getSize(); 
      offScreen = createImage(dim.width, dim.height); 
      bufferGraphics = offScreen.getGraphics(); 
      repaint(); 
      revalidate(); 
     } 
     //other methods of ComponentListener not shown 
    }); 
} 

@Override 
protected void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    g.drawImage(offScreen, 0, 0, null); 
} 

public void drawGrid(){ 
    int width = dim.width - insets.left - insets.right; 
    width -= (width % plateSize.getXSize()); 
    int height = (int) (width*Utils.PLATE_RATIO); 
    height -= (height % plateSize.getYSize()); 
    int step = pixelSize*gridSpacing; 
    Color bright = new Color(255, 255, 255, 100); 
    Color transparent = new Color(255, 255, 255, 20); 
    for(int ix = insets.left + step;       
      ix < (width+insets.left); ix += step){ 
     if(((ix - insets.left)/step) % 10 == 0){ 
      bufferGraphics.setColor(bright); 
     } 
     else{ 
      bufferGraphics.setColor(transparent); 
     } 
     //I am now drawing on bufferGraphics instead 
     //of the component Graphics 
     bufferGraphics.drawLine(ix, insets.top, ix, height+insets.top); 
    } 
    step *= Utils.PLATE_RATIO; 
    for(int iy = insets.top+step; 
      iy < (insets.top + height); iy += step){ 
     if(((iy - insets.top)/step) % 10 == 0){ 
      bufferGraphics.setColor(bright); 
     } 
     else{ 
      bufferGraphics.setColor(transparent); 
     } 
     bufferGraphics.drawLine(insets.left, iy, width + insets.left, iy); 
    } 
} 

P.S :이 내 질문에 편집으로 추가해야하는 경우, 말해 나는 그것을 할 드리겠습니다.

+0

Jesus, 이중 버퍼링 전략을 사용하는 JComponent를 확장하지 않는 것이 좋습니다. 실제로 모든 Swing 구성 요소에는 기본적으로이 구성이 사용됩니다. 그러면 많은 시간을 절약 할 수 있고 바퀴를 발명 할 필요가 없습니다 ... JComponent를 확장 할 때 필요한 것은 paintComponent 메소드를 확장하는 것입니다. 그렇습니다! 페인트! 그게 다야. 더블 버퍼링에 대해 걱정할 필요가 없습니다. –

+0

한 가지 더 - 의미없는 그림을 피하기 위해'getVisibleRect()'메서드를 사용하여 언급 한 내용을 얻지 못했습니다. 나는 구성 요소에서 볼 수없는 선 (및 선의 부분)을 제외하는 것에 대해 이야기하고있었습니다. 예를 들어 구성 요소가 활성 스크롤 안에 포함되어있는 경우 한 번에 일부만 볼 수 있습니다. 가능할 때 그 보이는 부분 바깥으로 그리는 것을 피해야합니다. 귀하의 경우에는 보이지 않는 선을 쉽게 제외 할 수 있습니다. –

+0

@MikleGarin 지금 문제가 무엇인지 이해했습니다. 실제로'drawGrid (Graphics g)'를 다른 함수에서 호출하고 있었지만,'painComponent (Graphics g)'만이 자동으로 더블 - 더핑되고 JComponent의 그래픽으로 그려지는 것은 아니라고 생각합니다. 어쨌든'paintComponent (...)'밖에서'drawGrid (...) '메서드를 호출하면 쉽게 구현할 수 있으므로 구현을 유지할 것이다. 'getVisibleRect()'에 대한 코멘트를 주셔서 감사합니다. – Nicolas