2013-04-06 1 views
4

두 개의 행을 별도로 호출하는 Java의 Canvas에 두 개의 선을 그려야하지만 두 번째 선을 그릴 때 첫 번째 선이 사라집니다 (Java는 화면을 지 웁니다). 어떻게 피할 수 있습니까? 나는 두 줄을보고 싶다. 필자는 사용자가 마우스를 사용하여 선을 그리고 한 선을 그리면 다른 선이 사라지지 않는 페인트 자습서 (Windows에서 그림판 같은 프로그램을 만드는 방법)를 보았습니다. 그들은 단지 paint 메소드를 호출하고 화면을 지우지 않습니다.페인트 방법을 호출 할 때 Java 화면이 지워집니다 - 어떻게 피할 수 있습니까?

누구든지 나를 도와 주시면 감사하겠습니다. 감사합니다. .

보기 클래스

import java.awt.BorderLayout; 
import java.awt.Canvas; 
import java.awt.Color; 
import java.awt.Graphics; 

import javax.swing.JFrame; 

public class CircuitTracePlotView extends JFrame { 


    private CircuitTracePlot circuitTracePlot; 

    public CircuitTracePlotView() { 


     this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     this.getContentPane().add(circuitTracePlot = new CircuitTracePlot(), BorderLayout.CENTER); 
     this.pack(); 
     this.setSize(250,250); 
     this.setLocationRelativeTo(null); 

     this.setVisible(true); 
     circuitTracePlot.drawLine(); 
     circuitTracePlot.drawOval(); 
    } 


} 

class CircuitTracePlot extends Canvas { 

    private final static short LINE = 1; 
    private final static short OVAL = 2; 
    private int paintType; 

    private int x1; 
    private int y1; 
    private int x2; 
    private int y2; 

    public CircuitTracePlot() { 
     this.setSize(250,250); 
     this.setBackground(Color.WHITE); 

    } 

    private void setPaintType(int paintType) { 
     this.paintType = paintType; 
    } 

    private int getPaintType() { 
     return this.paintType; 
    } 

    public void drawLine() { 
     this.setPaintType(LINE); 
     this.paint(this.getGraphics()); 
    } 

    public void drawOval() { 
     this.setPaintType(OVAL); 
     this.paint(this.getGraphics()); 
    } 

    public void repaint() { 
     this.update(this.getGraphics()); 
    } 

    public void update(Graphics g) { 
     this.paint(g); 
    } 

    public void paint(Graphics g) { 
     switch (paintType) { 
     case LINE: 
      this.getGraphics().drawLine(10, 10, 30, 30);    
     case OVAL: 
      this.getGraphics().drawLine(10, 20, 30, 30); 
     } 


    } 


} 

Main 클래스

import javax.swing.SwingUtilities; 

import view.CircuitTracePlotView; 

public class Main { 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       CircuitTracePlotView cr = new CircuitTracePlotView(); 
      } 
     }); 
    } 
} 
+0

+1 [sscce] (http://sscce.org/). – trashgod

답변

4
  • 당신은 거의 절대 직접 paint(...)를 호출 없습니다. 한 번에이 작업을 수행하는 데 필요한 시간을 계산할 수 있습니다.
  • 구성 요소에서 getGraphics()을 호출하여 Graphics 객체를 가져 오지 마십시오.이 객체는 비 지속성 Graphics 객체를 반환합니다. 대신에 BufferedImage를 드로잉 해 paint 메서드로 표시하는지, 페인트 메서드 (AWT 인 경우)를 묘화합니다.
  • Swing GUI이므로 AWT 구성 요소를 사용하지 마십시오. JPanel을 사용하고 paint(...) 메서드가 아닌 paintComponent(...) 메서드를 재정의하십시오. 그렇지 않으면 자동 이중 버퍼링을 포함한 스윙 그래픽의 모든 이점을 잃게됩니다.
  • super.paintComponent(g) 메서드는 paintComponent(Graphics g) 재정의에서 호출해야하며, 종종이 메서드의 첫 번째 메서드 호출로 호출해야합니다. 이를 통해 구성 요소에서 지워야하는 도면을 지우는 것을 포함하여 자체 관리 작업을 수행 할 수 있습니다.
  • 스윙 그래픽에 대한 자습서를 읽어보십시오. 대부분의 설명이 여기에 있습니다. 예를 들어, 여기 좀 준비하시기 바랍니다

편집

  • 가지고있는 이미지가 지속을, 난 당신이 BufferedImage의 그릴 것을 제안 그런 다음 JPanel의 paintComponent(...) 메소드에 해당 이미지를 표시하십시오.
  • 또 다른 옵션은 도형 객체의 컬렉션 (ArrayList<Shape>)을 만들고 그릴 도형으로 채운 다음 paintComponent(...) 메서드에서 Graphics 객체를 Graphics2D 객체로 캐스팅하고 해당 도형을 반복하는 것입니다. 반복 할 때 각 모양을 g2d.draw(shape)으로 그리는 컬렉션.
  • 휴지통 자신의 코드를 게시 때문에

, ...

import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.*; 

public class CircuitTracePlot2 extends JPanel { 

    private static final int PREF_W = 250; 
    private static final int PREF_H = PREF_W; 

    private int drawWidth = 160; 
    private int drawHeight = drawWidth; 
    private int drawX = 10; 
    private int drawY = 10; 
    private PaintType paintType = PaintType.LINE; 

    public CircuitTracePlot2() { 

    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(PREF_W, PREF_H); 
    } 

    public void setPaintType(PaintType paintType) { 
     this.paintType = paintType; 
     repaint(); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     if (paintType == null) { 
     return; 
     } 
     switch (paintType) { 
     case LINE: 
     g.drawLine(drawX, drawY, drawWidth, drawHeight); 
     break; 
     case OVAL: 
     g.drawOval(drawX, drawY, drawWidth, drawHeight); 
     break; 
     case SQUARE: 
     g.drawRect(drawX, drawY, drawWidth, drawHeight); 

     default: 
     break; 
     } 
    } 

    private static void createAndShowGui() { 
     final CircuitTracePlot2 circuitTracePlot = new CircuitTracePlot2(); 

     JFrame frame = new JFrame("CircuitTracePlot2"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(circuitTracePlot); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 

     int timerDelay = 2 * 1000; 
     new Timer(timerDelay , new ActionListener() { 
     private int paintTypeIndex = 0; 

     @Override 
     public void actionPerformed(ActionEvent arg0) { 
      paintTypeIndex++; 
      paintTypeIndex %= PaintType.values().length; 
      circuitTracePlot.setPaintType(PaintType.values()[paintTypeIndex]); 
     } 
     }).start(); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

enum PaintType { 
    LINE, OVAL, SQUARE; 
} 
+0

스윙 그래픽 튜토리얼의 URL을 알려주시겠습니까? 정확히 내가 원하는 것을 찾지 못했습니다 (어쩌면 자습서를 찾은 것일 수도 있지만 그 대답은 보이지 않습니다). BufferedImage로 무언가를 시도했지만 동일한 문제가 발생합니다. – vicaba

+0

@vicaba : 링크가 위에 추가되었습니다. BufferedImages로 그리기에 대한 자세한 내용은 많은 예제가 있으므로이 사이트를 검색 할 수 있습니다. –

+0

@vicaba : BufferedImage가 아니라 예제를 참조하십시오 .... –

2

여기 호버의 도움이 조언 @ 많이 구현 프로그램의 변형입니다. 효과를 보려면 setPaintType()로 전화를 걸어보십시오.

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

/** @see http://stackoverflow.com/a/15854246/230513 */ 
public class Main { 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       CircuitTracePlotView cr = new CircuitTracePlotView(); 
      } 
     }); 
    } 

    private static class CircuitTracePlotView extends JFrame { 

     private CircuitTracePlot plot = new CircuitTracePlot(); 

     public CircuitTracePlotView() { 
      this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
      plot.setPaintType(CircuitTracePlot.OVAL); 
      this.add(plot, BorderLayout.CENTER); 
      this.pack(); 
      this.setLocationRelativeTo(null); 
      this.setVisible(true); 
     } 
    } 

    private static class CircuitTracePlot extends JPanel { 

     public final static short LINE = 1; 
     public final static short OVAL = 2; 
     private int paintType; 

     public CircuitTracePlot() { 
      this.setBackground(Color.WHITE); 
     } 

     public void setPaintType(int paintType) { 
      this.paintType = paintType; 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      switch (paintType) { 
       case LINE: 
        g.drawLine(10, 10, 30, 30); 
       case OVAL: 
        g.drawOval(10, 20, 30, 30); 
       default: 
        g.drawString("Huh?", 5, 16); 
      } 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(250, 250); 
     } 
    } 
} 
+0

그게 효과가 있어요! 그러나 ... 나는 무슨 일이 일어나는 지 깨닫지 못한다. 나는 무엇이 일어 났는지 설명하려고 노력할 것이다. (내가 틀렸다면 나에게 맞춰라.) paintComponent() 위에있는 "one"이 어떤 속성 즉, 내부의 paintComponent가 변경되면, 위에서 "one"이 paintComponent()를 호출합니까? 그리고 왜 화면이 지금 지워지지 않았습니까? paintComponent()의 자동 버퍼링과 관련된 것이 있습니까? 정말 고마워요. – vicaba

+0

@vicaba : 천만에요. 페인팅 작동 방법에 대한 자세한 내용은 [* AWT 및 Swing * 페인팅] (http://www.oracle.com/technetwork/java/painting-140037.html)을 참조하십시오. – trashgod