2013-01-03 2 views
1

자바에서 나침반을 작업 중입니다. 먼저 나침반을위한 UI 프로토 타입을 만들고 SSCCE를 만들었습니다. 여기에서 패널을 클릭하면 약 15도 다른 방향으로 바늘이 향하게됩니다. 이 코드는 다음과 같습니다.나침반 바늘이 잘못된 위치에 그려졌습니다.

public class TestFrame extends JFrame { 

    public TestFrame() { 
     initComponents(); 
    } 

    public void initComponents() { 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setLocation(new Point((int) (Toolkit.getDefaultToolkit().getScreenSize().width/2) - 400, (int) (Toolkit.getDefaultToolkit().getScreenSize().height/2) - 250)); 
     setSize(500, 500); 
     setVisible(true); 
     CompassPanel c = new CompassPanel(); 
     add(c, BorderLayout.CENTER); 

    } 

    public class CompassPanel extends JPanel { 
     Image bufImage; 
     Graphics bufG; 
     private int circleX, circleY, circleRadius; 
     private int[] xPoints, yPoints; 
     private double rotationAngle = Math.toRadians(0); 

     public CompassPanel() { 
      setVisible(true); 

      addMouseListener(new MouseListener() { 
       @Override 
       public void mouseReleased(MouseEvent e) { 
       } 

       @Override 
       public void mousePressed(MouseEvent e) { 
       } 

       @Override 
       public void mouseExited(MouseEvent e) { 
       } 

       @Override 
       public void mouseEntered(MouseEvent e) { 
       } 

       @Override 
       public void mouseClicked(MouseEvent e) { 
        rotationAngle = rotationAngle + Math.toRadians(15); 
        repaint(); 
       } 
      }); 

     } 

     @Override 
     public void paint(Graphics g) { 
      super.paint(g); 
      Graphics2D g2d = (Graphics2D) g; 
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
      circleRadius = (int) (getWidth() * 0.7); 
      circleX = 50; 
      circleY = 50; 

      g2d.setColor(Color.BLACK); 
      for (int angle = 0; angle <= 360; angle += 5) { 
       double sin = Math.sin(Math.toRadians(angle)); 
       double cos = Math.cos(Math.toRadians(angle)); 
       int x1 = (int) ((circleX + circleRadius/2) - cos * (circleRadius * 0.37) - sin * (circleRadius * 0.37)); 
       int y1 = (int) ((circleY + circleRadius/2) + sin * (circleRadius * 0.37) - cos * (circleRadius * 0.37)); 
       g2d.setColor(Color.BLACK); 
       g2d.drawLine(x1, y1, (circleX + circleRadius/2), (circleY + circleRadius/2)); 
      } 

      g2d.setFont(new Font("Arial", Font.BOLD, 11)); 
      g2d.drawString("WEST", circleX - 45, circleY + circleRadius/2 + 4); 
      g2d.drawString("EAST", circleX + circleRadius + 13, circleY + circleRadius/2 + 4); 
      g2d.drawString("NORTH", circleX + circleRadius/2 - 14, circleY - 15); 
      g2d.drawString("SOUTH", circleX + circleRadius/2 - 14, circleY + circleRadius + 25); 
      g2d.setColor(Color.WHITE); 
      g2d.fillOval(circleX, circleY, circleRadius, circleRadius); 
      g2d.setColor(Color.BLACK); 
      g2d.drawOval(circleX, circleY, circleRadius, circleRadius); 

      xPoints = new int[] { (int) (circleX + circleRadius/2), 
        (int) (circleX + circleRadius * 0.25), 
        (int) (circleX + circleRadius/2), 
        (int) (circleX + circleRadius * 0.75) }; 

      yPoints = new int[] { (int) (circleY + 30), 
        (int) (circleY + circleRadius * 0.85), 
        (int) (circleY + circleRadius * 0.6), 
        (int) (circleY + circleRadius * 0.85) }; 

      Polygon fillPoly = new Polygon(xPoints, yPoints, 4); 
      Polygon outerPoly = new Polygon(xPoints, yPoints, 4); 

      int rotationX = circleX + (circleRadius/2); 
      int rotationY = circleX + (circleRadius/2); 

      g2d.setColor(Color.green); 
      g2d.fillOval(rotationX, rotationY, 5, 5); 

      AffineTransform a = g2d.getTransform().getRotateInstance(rotationAngle, rotationX, rotationY); 
      g2d.setTransform(a); 

      g2d.setColor(Color.RED); 
      g2d.fillPolygon(fillPoly); 

      g2d.setColor(Color.black); 
      g2d.draw(outerPoly); 
     } 

     @Override 
     public void update(Graphics g) { 
      int w = this.getSize().width; 
      int h = this.getSize().height; 

      if (bufImage == null) { 
       bufImage = this.createImage(w, h); 
       bufG = bufImage.getGraphics(); 
      } 

      bufG.setColor(this.getBackground()); 
      bufG.fillRect(0, 0, w, h); 
      bufG.setColor(this.getForeground()); 

      paint(bufG); 
      g.drawImage(bufImage, 0, 0, this); 
     } 

     public void setRotationAngle(int angle) { 
      rotationAngle = angle; 
     } 
    } 

    public static void main(String[] args) { 
     new TestFrame(); 
    } 
} 

이 응용 프로그램을이 응용 프로그램에 구현하면 바늘이 SSCCE에 그대로 그려지지 않습니다. 조금 더 높게 그려지는 위치의 왼쪽에 그려져 있습니다. 패널을 클릭하고 바늘을 회전하면 회전이 잘 작동하고 바늘이 속한 곳이 그려집니다.

나는이 응용 프로그램을 내 응용 프로그램에 추가합니다. sensorPanel은 TabbedPaneJPanel입니다.

public JPanel createSensorPanel(){ 
    sensorPanel = new JPanel(new MigLayout("fill, insets 3")); 
    CompassPanel compassPanel = new CompassPanel(); 
    sensorPanel.add(compassPanel, "wrap"); 
    return sensorPanel; 
} 

왜 바늘의 Polygon는이 SSCCE에 그려진 위치에 그려되지 않는 이유는 무엇입니까?

편집 :

다음은 문제의 그림입니다. picture

+0

문제가있는 스크린 샷을 게시 할 수 있습니까? – Sorceror

+0

setLocation (Toolkit.getDefaultToolkit(). getDefaultToolkit(). getScreenSize(). width/2) - 400, (Toolkit.getDefaultToolkit(). getScreenSize(). height/2) - 250) setLocation ;setSize (500, 500);'해당 로트를'setLocationByPlatform (true);로 대체하십시오. 결과는 [here] (http://stackoverflow.com/a/7143398/418556)에서 볼 수 있습니다. –

답변

2

이미지에서 어떤 일이 일어나는지 자세히 살펴 본다면 아핀 변형이 문제입니다. 이 아핀 변환이 상위 부모없는 현재 자식 요소 (java Affine Transform correct order 참조)와 관련된 것처럼

enter image description here

보인다. 부모가 (this answer 기준) 번역으로

신속하고 더러운 솔루션은

AffineTransform a = g2d.getTransform(). 
    getRotateInstance(rotationAngle, rotationX, rotationY) 
    .translate(parent.getX(), parent.getY()) // use instance of real parent instead 
    .translate(tabpane.getX(), tabpane.getY()); // use instance of JTabbedPane instead 

그러나 훨씬 더 편리 몇 가지 일반적인 솔루션, this one 같은 것이있는 화살표를 번역하는 것입니다.

관련 문제