2017-03-10 2 views
1

드로잉을 할 때마다 반사를 켜고 모든 것을 그려야합니다. 그런 다음 반향을 해제하고 현재 그려야 할 포인트가 마우스 커서 아래에 나타나지 않습니다. 이상한 것은 때로는 잘 작동하고 몇 번이나 반사를 켜고 끄면 버그가 발생한다는 것입니다. 나는 그 뒤에 어떤 이유가 있는지 전혀 모른다. 여기에 코드가 있습니다. 제가 도와 주시면 매우 감사드립니다. 잘못된 위치에 드로잉 포인트가 있습니다

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Container; 
import java.awt.Dimension; 
import java.awt.FlowLayout; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.GridLayout; 
import java.awt.Image; 
import java.awt.Point; 
import java.awt.Toolkit; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.ComponentEvent; 
import java.awt.event.ComponentListener; 
import java.awt.event.ItemEvent; 
import java.awt.event.ItemListener; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.geom.Ellipse2D; 
import java.awt.geom.Line2D; 
import java.awt.image.BufferedImage; 
import java.util.ArrayList; 
import java.util.Iterator; 
import javax.swing.BorderFactory; 
import javax.swing.ImageIcon; 
import javax.swing.JButton; 
import javax.swing.JCheckBox; 
import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 

//3 inner classes because if this code is part of a bigger problem, these classes will not be used anywhere else and need to be encapsulated 
public class CWTEST extends JFrame{ 

    public CWTEST(String title){ 
     super(title); 
    } 

    public void initialiseGUI(){ 
     Container mainPanel = this.getContentPane(); 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
     //make the window as big as the screen without covering the windows taskbar 
     this.setBounds(0, 0, screenSize.width, screenSize.height-40); 

     //set up the displayPanel where the drawing is done 
     mainPanel.setLayout(new BorderLayout()); 
     DrawingPanel displayPanel = new DrawingPanel(); 
     mainPanel.add(displayPanel, BorderLayout.CENTER); 

     //set up the controlPanel where the user changes the drawing options 
     JPanel controlPanel = new JPanel(); 
     mainPanel.add(controlPanel, BorderLayout.SOUTH); 
     controlPanel.setLayout(new FlowLayout());                               
     controlPanel.setBorder(BorderFactory.createLineBorder(new java.awt.Color(0, 255, 0))); 


     JLabel reflectPointsLabel = new JLabel("reflect points"); 
     controlPanel.add(reflectPointsLabel); 

     JCheckBox reflectPointsBox = new JCheckBox(); 
     reflectPointsBox.addItemListener(new ItemListener(){ 
      @Override 
      public void itemStateChanged(ItemEvent e) { 
       if (e.getStateChange() == ItemEvent.SELECTED){ 
        displayPanel.reflectPoints = true; 
       }else{ 
        displayPanel.reflectPoints = false; 
       } 
      } 
     }); 
     controlPanel.add(reflectPointsBox); 
     reflectPointsBox.setSelected(false); 



     this.setVisible(true); 

     //once the frame is visible we can get the real size of the drawing panel and create a buffered image that matches it 
     displayPanel.buffImage = new BufferedImage(displayPanel.getWidth(), displayPanel.getHeight(), BufferedImage.TYPE_3BYTE_BGR);       
    } 




    public class DrawingPanel extends JPanel{ 
     //default drawing options                        
     private double circleDiameter = 5; 
     private Color color = Color.BLUE;         
     private boolean showSectors;           
     private boolean reflectPoints; 
     private int numOfSectors = 12; 
     //list of points to be drawn 
     private ArrayList<MyPoint> pointsList; 
     //buffered image on which the drawing is done and then copied to the JPanel 
     private BufferedImage buffImage;   

     public DrawingPanel(){ 
      this.setBackground(Color.BLACK); 
      DrawingListener listener = new DrawingListener(this); 
      this.addMouseListener(listener); 
      this.addMouseMotionListener(listener); 
      this.addComponentListener(listener); 
      pointsList = new ArrayList<MyPoint>();       
     }   

     public void paintComponent(Graphics g){ 
      super.paintComponent(g); 
      this.drawBuffImage(); 
      //copy what's drawn on the buffered image to the JPanel 
      g.drawImage(buffImage, 0,0, null); 
     } 

     public void drawBuffImage(){                                                
      Graphics2D g2d = buffImage.createGraphics(); 
      g2d.setColor(Color.WHITE); 

      //if there are more tan 1 sectors - draw lines to separate them 
      if(showSectors && numOfSectors > 1){ 
       Line2D line = new Line2D.Double(this.getWidth()/2,0,this.getWidth()/2,this.getHeight()/2); 

       //draw half a line every time and rotate the next according to the number of sectors 
       for(int w = 0; w < numOfSectors; w++){ 
        g2d.draw(line); 
        g2d.rotate(Math.toRadians((double) 360/numOfSectors), this.getWidth()/2, this.getHeight()/2); 
       } 
      } 

      //draw each point in the list 
      for(int i = 0; i < pointsList.size(); i++){ 
       MyPoint point = pointsList.get(i); 
       g2d.setColor(point.getPointColor()); 

       Ellipse2D circle = new Ellipse2D.Double(point.getX(), point.getY(), point.getPointDiameter(), point.getPointDiameter());    

       //draw the point once in each sector 
       for(int j = 0; j < numOfSectors; j++){       
        g2d.fill(circle); 
        g2d.rotate(Math.toRadians(((double) 360/numOfSectors)), this.getWidth()/2, this.getHeight()/2);                 
       }                       

       //if point should be reflected, draw its reflection in each sector 
       if(point.isReflected()){ 
        g2d.rotate(Math.toRadians((double) 360/(numOfSectors*2)), this.getWidth()/2, this.getHeight()/2); 
        g2d.fill(circle); 

        for(int t = 1; t < numOfSectors; t++){ 
         g2d.rotate(Math.toRadians((double) 360/numOfSectors), this.getWidth()/2, this.getHeight()/2); 
         g2d.fill(circle);                          
        } 
       } 
      } 

      g2d.dispose(); 
     } 

     public void wipeScreen(){ 
      //wipe everything by covering it with black 
      Graphics g = buffImage.createGraphics(); 
      g.setColor(Color.BLACK); 
      g.fillRect(0,0,buffImage.getWidth(),buffImage.getHeight()); 
      g.dispose(); 
     } 

     public void addPoint(MyPoint p){ 
      pointsList.add(p); 
     } 

     public void setColor(Color color){ 
      this.color = color; 
     } 

     public void setCircleDiameter(double circleDiameter){ 
      this.circleDiameter = circleDiameter; 
     } 
    } 

    public class DrawingListener extends MouseAdapter implements ComponentListener{ 
     //the panel on which the user draws 
     private DrawingPanel dPanel; 

     public DrawingListener(DrawingPanel dPanel){ 
      this.dPanel = dPanel; 
     } 

     //add a point to the arraylist every time the user draws, and draw 
     public void mousePressed(MouseEvent e) { 
      dPanel.addPoint(new MyPoint(e.getX(), e.getY(), dPanel.color, dPanel.circleDiameter, dPanel.reflectPoints)); 
      dPanel.repaint(); 
     } 

     public void mouseDragged(MouseEvent e) { 
      dPanel.addPoint(new MyPoint(e.getX(), e.getY(), dPanel.color, dPanel.circleDiameter, dPanel.reflectPoints)); 
      dPanel.repaint(); 
     } 

     @Override 
     public void componentResized(ComponentEvent e) { 
      //whenever component is resized, wipe the screen 
      //then the system-triggered repaint occurs and the result is that by making the window smaller, the user zooms in 
      dPanel.wipeScreen(); 
     } 

     public void componentHidden(ComponentEvent arg0) {} 
     public void componentMoved(ComponentEvent arg0) {} 
     public void componentShown(ComponentEvent arg0) {} 
    } 


    //each point drawn is an object of the class 
    public class MyPoint extends Point{ 
     private Color pointColor; 
     private double pointDiameter; 
     private boolean reflected; 

     public MyPoint(int x, int y, Color c, double pointDiameter, boolean reflected){ 
      super(x,y); 
      this.pointColor = c; 
      this.pointDiameter = pointDiameter; 
      this.reflected = reflected; 
     } 

     public Color getPointColor(){ 
      return this.pointColor; 
     } 

     public double getPointDiameter(){ 
      return this.pointDiameter; 
     } 

     public boolean isReflected(){ 
      return this.reflected; 
     } 
    } 

} 

public class MainTest { 

    public static void main(String[] args){ 
     CWTEST frame = new CWTEST("Digital Doily"); 
     frame.initialiseGUI(); 
    } 
} 

편집 상자가 내가 12 포인트를 획득 쳤다되지

- 가장 안쪽 원. 그런 다음 상자에 체크하고 24 점 (원본 12 점, 반사 12 점) - 두 번째 원 (리플렉션 있음)을 얻습니다. 그런 다음 상자를 풀어서 12 점을 얻습니다. 그러나 원이 제 1 원과 같은 동일한 위치에 있지만 이전 원에서 12 개의 반사 점 대신 그려집니다. 녹색 점은 반사 된 점의 예입니다. 두 점 사이의 점입니다. 빨간 점들은 마우스 커서가 모든 그림에있는 곳입니다. 세 번째 원을 만들면 반사가 해제되고 커서 아래에 점이 그려지지 않습니다.

enter image description here

+0

* "그러나 반사음을 끄고 내가 그린 점은 마우스 커서 아래에 나타나지 않습니다."* 설명 된 동작은 보이지 않지만 나도 체크 박스가 체크 된 시점과 그렇지 않은 시점 사이의 차이점을 확인하십시오. –

+0

@Andrew Thompson 나는 당신이 이해하도록 돕기 위해 그것을 편집했다. 도움이되기를 바랍니다. 때로는 버그를 가져 오기 위해 반사를 두 번 켜고 끌 필요가 있습니다. –

답변

3

나는 가끔 잘못 얻는 이유를 모르겠지만, 일반적으로 그릴 것이다 사용 AffineTransform#getRotateInstance(...)#createTransformedShape(...) 대신 Graphics2D#rotate(...)의를 보인다.

import java.awt.*; 
import java.awt.event.*; 
import java.awt.font.*; 
import java.awt.geom.*; 
import java.awt.image.BufferedImage; 
import java.util.ArrayList; 
import java.util.Iterator; 
import javax.swing.*; 

public class MainTest2 { 
    public static void main(String[] args) { 
    CWTEST frame = new CWTEST("Digital Doily"); 
    frame.initialiseGUI(); 
    } 
} 

class CWTEST extends JFrame { 

    public CWTEST(String title) { 
    super(title); 
    } 

    public void initialiseGUI() { 
    Container mainPanel = this.getContentPane(); 
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
    //make the window as big as the screen without covering the windows taskbar 
    this.setBounds(0, 0, screenSize.width, screenSize.height - 40); 

    //set up the displayPanel where the drawing is done 
    mainPanel.setLayout(new BorderLayout()); 
    DrawingPanel displayPanel = new DrawingPanel(); 
    mainPanel.add(displayPanel, BorderLayout.CENTER); 

    //set up the controlPanel where the user changes the drawing options 
    JPanel controlPanel = new JPanel(); 
    mainPanel.add(controlPanel, BorderLayout.SOUTH); 
    controlPanel.setLayout(new FlowLayout()); 
    controlPanel.setBorder(BorderFactory.createLineBorder(new java.awt.Color(0, 255, 0))); 


    JLabel reflectPointsLabel = new JLabel("reflect points"); 
    controlPanel.add(reflectPointsLabel); 

    JCheckBox reflectPointsBox = new JCheckBox(); 
    reflectPointsBox.addItemListener(new ItemListener() { 
     @Override 
     public void itemStateChanged(ItemEvent e) { 
     if (e.getStateChange() == ItemEvent.SELECTED) { 
      displayPanel.reflectPoints = true; 
     } else { 
      displayPanel.reflectPoints = false; 
     } 
     } 
    }); 
    controlPanel.add(reflectPointsBox); 
    reflectPointsBox.setSelected(false); 



    this.setVisible(true); 

    //once the frame is visible we can get the real size of the drawing panel and create a buffered image that matches it 
    displayPanel.buffImage = new BufferedImage(
     displayPanel.getWidth(), displayPanel.getHeight(), BufferedImage.TYPE_3BYTE_BGR); 
    } 




    public class DrawingPanel extends JPanel { 
    //default drawing options 
    private double circleDiameter = 5; 
    private Color color = Color.BLUE; 
    private boolean showSectors; 
    private boolean reflectPoints; 
    private int numOfSectors = 12; 
    //list of points to be drawn 
    private ArrayList<MyPoint> pointsList; 
    //buffered image on which the drawing is done and then copied to the JPanel 
    private BufferedImage buffImage; 

    public DrawingPanel() { 
     this.setBackground(Color.BLACK); 
     DrawingListener listener = new DrawingListener(this); 
     this.addMouseListener(listener); 
     this.addMouseMotionListener(listener); 
     this.addComponentListener(listener); 
     pointsList = new ArrayList<MyPoint>(); 
    } 

    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     this.drawBuffImage(); 
     //copy what's drawn on the buffered image to the JPanel 
     g.drawImage(buffImage, 0, 0, null); 
    } 

    public void drawBuffImage() { 
     Graphics2D g2d = buffImage.createGraphics(); 
     g2d.setColor(Color.WHITE); 

////if there are more tan 1 sectors - draw lines to separate them 
//if (showSectors && numOfSectors > 1) { 
// Line2D line = new Line2D.Double(this.getWidth()/2, 0, this.getWidth()/2, this.getHeight()/2); 
// 
// //draw half a line every time and rotate the next according to the number of sectors 
// for (int w = 0; w < numOfSectors; w++) { 
//  g2d.draw(line); 
//  g2d.rotate(Math.toRadians((double) 360/numOfSectors), this.getWidth()/2, this.getHeight()/2); 
// } 
// g2d.rotate(0d); 
//} 

     double angle = 360d/numOfSectors; 
     double ancx = this.getWidth()/2d; 
     double ancy = this.getHeight()/2d; 

     //draw each point in the list 
     for (int i = 0; i < pointsList.size(); i++) { 
     MyPoint point = pointsList.get(i); 
     g2d.setColor(point.getPointColor()); 

     Ellipse2D circle = new Ellipse2D.Double(
      point.getX(), point.getY(), point.getPointDiameter(), point.getPointDiameter()); 

     //draw the point once in each sector 
     double rotate = 0d; 
     for (int j = 0; j < numOfSectors; j++) { 
      rotate += angle; 
      AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(rotate), ancx, ancy); 
      g2d.fill(at.createTransformedShape(circle)); 
      //g2d.rotate(Math.toRadians(((double) 360/numOfSectors)), this.getWidth()/2, this.getHeight()/2); 
     } 

     //if point should be reflected, draw its reflection in each sector 
     if (point.isReflected()) { 
      //g2d.rotate(Math.toRadians((double) 360/(numOfSectors * 2)), this.getWidth()/2, this.getHeight()/2); 
      //g2d.fill(circle); 
      rotate = angle/2d; 
      g2d.setColor(Color.RED); 
      for (int t = 0; t < numOfSectors; t++) { 
      //g2d.rotate(Math.toRadians((double) 360/numOfSectors), this.getWidth()/2, this.getHeight()/2); 
      //g2d.fill(circle); 
      rotate += angle; 
      AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(rotate), ancx, ancy); 
      g2d.fill(at.createTransformedShape(circle)); 
      } 
     } 
     } 
     g2d.dispose(); 
    } 

    public void wipeScreen() { 
     //wipe everything by covering it with black 
     if (buffImage != null) { 
     Graphics g = buffImage.createGraphics(); 
     g.setColor(Color.BLACK); 
     g.fillRect(0, 0, buffImage.getWidth(), buffImage.getHeight()); 
     g.dispose(); 
     } 
    } 

    public void addPoint(MyPoint p) { 
     pointsList.add(p); 
    } 

    public void setColor(Color color) { 
     this.color = color; 
    } 

    public void setCircleDiameter(double circleDiameter) { 
     this.circleDiameter = circleDiameter; 
    } 
    } 

    public class DrawingListener extends MouseAdapter implements ComponentListener { 
    //the panel on which the user draws 
    private final DrawingPanel dPanel; 

    public DrawingListener(DrawingPanel dPanel) { 
     this.dPanel = dPanel; 
    } 

    //add a point to the arraylist every time the user draws, and draw 
    public void mousePressed(MouseEvent e) { 
     //System.out.println(e.getPoint()); 
     dPanel.addPoint(new MyPoint(e.getX(), e.getY(), dPanel.color, dPanel.circleDiameter, dPanel.reflectPoints)); 
     dPanel.repaint(); 
    } 

    public void mouseDragged(MouseEvent e) { 
     dPanel.addPoint(new MyPoint(e.getX(), e.getY(), dPanel.color, dPanel.circleDiameter, dPanel.reflectPoints)); 
     dPanel.repaint(); 
    } 

    @Override 
    public void componentResized(ComponentEvent e) { 
     //whenever component is resized, wipe the screen 
     //then the system-triggered repaint occurs and the result is that by making the window smaller, the user zooms in 
     dPanel.wipeScreen(); 
    } 

    public void componentHidden(ComponentEvent arg0) {} 
    public void componentMoved(ComponentEvent arg0) {} 
    public void componentShown(ComponentEvent arg0) {} 
    } 


    //each point drawn is an object of the class 
    public class MyPoint extends Point { 
    private Color pointColor; 
    private double pointDiameter; 
    private boolean reflected; 

    public MyPoint(int x, int y, Color c, double pointDiameter, boolean reflected) { 
     super(x, y); 
     this.pointColor = c; 
     this.pointDiameter = pointDiameter; 
     this.reflected = reflected; 
    } 

    public Color getPointColor() { 
     return this.pointColor; 
    } 

    public double getPointDiameter() { 
     return this.pointDiameter; 
    } 

    public boolean isReflected() { 
     return this.reflected; 
    } 
    } 
} 
+0

감사합니다! 나는 아직도 버그가 무엇인지 궁금해. –

+1

@ScottyNguyen : 반복 된 변형, 예 : 'rotate()'에 대한 호출은 [here] (http://stackoverflow.com/a/3843569/230513)에서 논의 된 방식으로 _ 조합됩니다. 'AffineTransform'에서 개입하지 않고'createTransformedShape()'를 반복적으로 호출하는 것은 아닙니다. – trashgod

관련 문제