我想做一条有向线并使其移动。我可以画一条有方向的线并移动线,但是在移动线时箭头会移位

这是我的绘画方法

 Line2D.Double line = new Line2D.Double(startX, startY, endX, endY);
                    g2d.draw(line);
                    tx.setToIdentity();
                  double angle = Math.atan2(line.y2 - line.y1, line.x2 - line.x1);
                   tx.translate(line.x2, line.y2);
                    tx.rotate((angle - Math.PI / 2d));
                    Graphics2D gClone = (Graphics2D) g2d.create();
                    gClone.setTransform(tx);
 Polygon arrowHead = new Polygon();
        arrowHead.addPoint(0, 15);
        arrowHead.addPoint(-15, -15);
        arrowHead.addPoint(15, -15);
                    Area area = new Arear(arrowHead );
                    Area lineArea = new Area(line);
                    lineArea.subtract(area);
                    gClone.fill(area);
                    gClone.dispose();


我已经更改了startx和y的值,在按下鼠标时
和endx和enny在鼠标拖动

最佳答案

这是一个基本示例,演示了如何使用Path2D定义自定义形状,并使用AffineTransformation来转换形状。

此示例将导致箭头在面板上移动时指向鼠标



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.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class RotateArrow {

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

    public RotateArrow() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new RotatePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class RotatePane extends javax.swing.JPanel {

        private Point mousePoint;
        private PointyThing pointyThing;

        public RotatePane() {

            pointyThing = new PointyThing();

            addMouseMotionListener(new MouseAdapter() {
                @Override
                public void mouseMoved(MouseEvent e) {
                    mousePoint = e.getPoint();
                    repaint();
                }
            });

        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g.create();

            double rotation = 0f;

            int width = getWidth() - 1;
            int height = getHeight() - 1;

            if (mousePoint != null) {
                int x = width / 2;
                int y = height / 2;

                int deltaX = mousePoint.x - x;
                int deltaY = mousePoint.y - y;

                rotation = -Math.atan2(deltaX, deltaY);
                rotation = Math.toDegrees(rotation) + 180;
            }

            Rectangle bounds = pointyThing.getBounds();

            AffineTransform at = new AffineTransform();
            at.translate((width - bounds.width) / 2, (height - bounds.height) / 2);
            at.rotate(Math.toRadians(rotation), bounds.width / 2, bounds.height / 2);
            Shape shape = new Path2D.Float(pointyThing, at);

            g2d.setStroke(new BasicStroke(3));
            g2d.setColor(Color.RED);

            g2d.fill(shape);
            g2d.draw(shape);
            g2d.dispose();
        }
    }

    public class PointyThing extends Path2D.Float {

        public PointyThing() {
            moveTo(15, 0);
            lineTo(30, 15);
            lineTo(0, 15);
            lineTo(15, 0);
            moveTo(15, 15);
            lineTo(15, 60);
        }

    }
}


用示例二进行更新

基本上,这仅将PointyThing用作箭头,并分别绘制线条。

箭头已定向,因此它将指向直线下方(朝着鼠标)

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.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class RotateArrow {

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

    public RotateArrow() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new RotatePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class RotatePane extends javax.swing.JPanel {

        private PointyThing pointyThing;
        private Point mouseStart;
        private Point mouseEnd;

        public RotatePane() {

            pointyThing = new PointyThing();

            MouseAdapter ma = new MouseAdapter() {
                @Override
                public void mouseMoved(MouseEvent e) {
                    mouseEnd = e.getPoint();
                    repaint();
                }

                @Override
                public void mouseClicked(MouseEvent e) {
                    mouseStart = e.getPoint();
                    repaint();
                }
            };

            addMouseListener(ma);
            addMouseMotionListener(ma);

        }

        @Override
        public Dimension getPreferredSize() {

            return new Dimension(200, 200);

        }

        @Override
        protected void paintComponent(Graphics g) {

            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g.create();
            if (mouseStart != null && mouseEnd != null) {

                double rotation = 0f;

                int width = getWidth() - 1;
                int height = getHeight() - 1;

                if (mouseEnd != null) {

                    int x = mouseStart.x;
                    int y = mouseStart.y;

                    int deltaX = mouseEnd.x - x;
                    int deltaY = mouseEnd.y - y;

                    rotation = -Math.atan2(deltaX, deltaY);
                    rotation = Math.toDegrees(rotation) + 180;

                }

                Rectangle bounds = pointyThing.getBounds();

                g2d.setStroke(new BasicStroke(3));
                g2d.setColor(Color.RED);
                g2d.draw(new Line2D.Float(mouseStart, mouseEnd));

                AffineTransform at = new AffineTransform();

                at.translate(mouseEnd.x - (bounds.width / 2), mouseEnd.y - (bounds.height / 2));
                at.rotate(Math.toRadians(rotation), bounds.width / 2, bounds.height / 2);
                Shape shape = new Path2D.Float(pointyThing, at);

                g2d.fill(shape);
                g2d.draw(shape);
            }
            g2d.dispose();

        }

    }

    public class PointyThing extends Path2D.Float {

        public PointyThing() {
            moveTo(15, 0);
            lineTo(30, 15);
            lineTo(0, 15);
            lineTo(15, 0);
        }

    }

}

08-18 07:52