【问题标题】:How to draw a arrow with java2d?如何用java2d画一个箭头?
【发布时间】:2018-03-21 00:06:31
【问题描述】:

我正在尝试画一个圆圈中的箭头(如时钟指针),但我无法将箭头的尖端与线条的其余部分对齐。

我根据this answer 制作了“箭头”,但无法使其与线条图正确定位。

箭头更偏向行的左侧,如下图所示:

这是我的 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);
        }

    }

}

【问题讨论】:

    标签: java swing java-2d


    【解决方案1】:

    您正在重置转换。

    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);
    }
    

    【讨论】:

    • 不想滥用您的善意,但为什么会这样?如果我删除this.contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));,箭头就会正常。
    • 边框就是问题所在。边框为 5 像素宽。绘制组件时,边框是组件的一部分,因此坐标 (0, 0) 将位于边框“外部”。绘制线条时,Graphics2D 的默认 Transformation 通过添加 (5, 5) 的平移(= 边框的宽度)来补偿这种效果。但是当你设置你的转换时,你首先将它设置为标识,然后缺少这个额外的转换,导致边框宽度不对齐。
    • Graphics2D 的 Javadoc:创建 Graphics2D 对象时,GraphicsConfiguration 指定 Graphics2D 目标(组件或图像)的默认变换。此默认转换将用户空间坐标系映射到屏幕和打印机设备坐标,以便原点映射到设备目标区域的左上角,其中增加的 X 坐标向右延伸,增加的 Y 坐标向下延伸
    • @cello 很有趣。我现在开始深入研究java2d,不知道AffineTransform类在组件构建中的重要性。感谢您的解释。感谢安德烈亚斯回答:D
    猜你喜欢
    • 2018-11-18
    • 2015-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-01
    • 2013-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多