2017-10-09 17 views
1

私は円の中に(クロックポインタのように)矢印を描こうとしていますが、矢印の先端を残りの行と揃えられません。java2dで矢印を描くには?

私は矢印をthis answerに基づいて作成しましたが、線の描画で正しく配置されるようにすることはできません。

画像に次のように矢印は、行の左側によります:

print screen

ここに私のMCVE:

import java.awt.BasicStroke; 
import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Polygon; 
import java.awt.geom.AffineTransform; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.border.EmptyBorder; 

public class LineArrowTest extends JFrame { 

    private static final long serialVersionUID = 1L; 
    private JPanel contentPane; 
    private JPanel DrawPanel; 

    public static void main(String[] args) { 
     EventQueue.invokeLater(() -> { 
      new LineArrowTest().setVisible(true); 
     }); 
    } 

    public LineArrowTest() { 
     initComponents(); 
     pack(); 
    } 

    private void initComponents() { 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setPreferredSize(new Dimension(400, 300)); 
     this.contentPane = new JPanel(new BorderLayout(0, 0)); 
     this.contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 
     setContentPane(this.contentPane); 

     this.DrawPanel = new JPanel() { 

      @Override 
      protected void paintComponent(Graphics g) { 
       super.paintComponent(g); 
       LineArrow line = new LineArrow(getWidth()/2, getHeight()/2, getWidth()/2, getHeight(), 
         Color.black, 3); 
       line.draw(g); 
      } 
     }; 
     this.contentPane.add(this.DrawPanel, BorderLayout.CENTER); 
    } 

    class LineArrow { 

     int x; 
     int y; 
     int endX; 
     int endY; 
     Color color; 
     int thickness; 

     public LineArrow(int x, int y, int x2, int y2, Color color, int thickness) { 
      super(); 
      this.x = x; 
      this.y = y; 
      this.endX = x2; 
      this.endY = y2; 

      this.color = color; 
      this.thickness = thickness; 
     } 

     public void draw(Graphics g) { 
      Graphics2D g2 = (Graphics2D) g.create(); 

      g2.setColor(color); 
      g2.setStroke(new BasicStroke(thickness)); 
      g2.drawLine(x, y, endX, endY); 
      ; 
      drawArrowHead(g2); 
      g2.dispose(); 
     } 

     private void drawArrowHead(Graphics2D g2) { 

      Polygon arrowHead = new Polygon(); 
      AffineTransform tx = new AffineTransform(); 

      arrowHead.addPoint(0, 5); 
      arrowHead.addPoint(-5, -5); 
      arrowHead.addPoint(5, -5); 

      tx.setToIdentity(); 
      double angle = Math.atan2(endY - y, endX - x); 
      tx.translate(endX, endY); 
      tx.rotate(angle - Math.PI/2d); 

      g2.setTransform(tx); 
      g2.fill(arrowHead); 
     } 

    } 

} 

答えて

2

あなたが変換をリセットしています。

AffineTransform tx = new AffineTransform();~AffineTransform tx = g2.getTransform();を変更し、tx.setToIdentity();コールを削除してください。

以下のコードも、関連するステートメントをまとめて整理するために再編成されました。

private void drawArrowHead(Graphics2D g2) { 
    double angle = Math.atan2(endY - y, endX - x); 
    AffineTransform tx = g2.getTransform(); 
    tx.translate(endX, endY); 
    tx.rotate(angle - Math.PI/2d); 
    g2.setTransform(tx); 

    Polygon arrowHead = new Polygon(); 
    arrowHead.addPoint(0, 5); 
    arrowHead.addPoint(-5, -5); 
    arrowHead.addPoint(5, -5); 
    g2.fill(arrowHead); 
} 
+0

あなたののれんを悪用したくないのですが、どうしてですか? 'this.contentPane.setBorder(new EmptyBorder(5、5、5、5)); 'を削除すると、矢印は正常になります。 – Articuno

+0

ボーダーはまさに問題です。境界線の幅は5ピクセルです。コンポーネントを描画するとき、ボーダーはコンポーネントの一部であるため、座標(0、0)はボーダーの「外側」になります。線を描画するとき、Graphics2Dのデフォルトの変換は、(5,5)の平行移動(=境界線の幅)を加えることによってこの効果を補う。しかし、トランスフォーメーションを設定するときは、最初にアイデンティティに設定してから、この追加の変換が欠落し、正確に境界線の幅が正しく配置されなくなります。 – cello

+0

['Graphics2D']のJavadoc(https://docs.oracle.com/javase/8/docs/api/java/awt/Graphics2D.html):* Graphics2Dオブジェクトを作成するとき、GraphicsConfigurationはデフォルトの変換を指定しますGraphics2Dのターゲット(ComponentまたはImage)このデフォルトの変換では、ユーザ空間座標系が画面とプリンタのデバイス座標にマップされ、原点がデバイスのターゲット領域の左上隅にマップされ、X座標が右に伸び、Y座標が下に延びるようになります。* – Andreas

関連する問題