【Java AWT 图形界面编程】在 Canvas 画布中绘制箭头图形 ( 数据准备 | 几个关键的计算公式 | 绘制箭头直线和尾翼 )

该文章详细介绍了如何在Java的Canvas组件中绘制箭头图形,包括数据准备、绘制直线以及绘制箭头尾翼的步骤。通过计算直线的角度和使用数学公式确定箭头的位置和尾翼,提供了一段完整的代码示例来展示实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >





一、在 Canvas 画布中绘制箭头图形 - 要点分析




1、数据准备


绘制箭头时 , 先设置一条直线的起始点和终止点 , 箭头绘制在该线段上 ;

    /**
     * 起始点 X, Y 坐标
     * 终止点 X, Y 坐标
     */
    private int startX, startY, endX, endY;

为箭头指定一个长度 , 该长度的末尾是 箭头终点 , 在直线上确定箭头终点 , 该终点延伸出两个尾翼 , 尾翼也指定一个长度 ;

    /**
     * 箭头 左右两个尾翼 长度
     */
    private int arrowWingLength = 20;

    /**
     * 箭头终点在直线的位置
     */
    private float arrowEndRatio = 0.5F;

    /**
     * 箭头长度
     */
    private int arrowLength;

2、绘制直线


先把箭头附着的直线 , 绘制出来 ;

        // 绘制直线
        g.drawLine(startX, startY, endX, endY);

3、绘制箭头尾翼


首先 , 确定起始点和终止点 , 在 x , y 轴上的差值 ;

        // 计算起始点和终止点在 x, y 方向的差值
        int deltaX = endX - startX;
        int deltaY = endY - startY;

然后 , 计算出起始点到终止点的角度 , deltaY / deltaX 是该角度的正切 , 已知正切值 , 计算角度 , 使用 Math.atan2 函数即可 , 最终计算的角度是 该直线 与 x 轴夹角 ;

在这里插入图片描述

        // 计算 直线的角度
        double angle = Math.atan2(deltaY, deltaX);

再后 , 使用勾股定理计算直线的长度 ;

        // 计算直线的长度
        int len = (int) Math.sqrt(deltaX * deltaX + deltaY * deltaY);

再后 , 根据比例计算出箭头的长度 , 根据该长度 , 确定箭头终点的坐标 ; 下图中蓝色的箭头 , 就是计算出的箭头尾部相对于起始点的增量 ;

在这里插入图片描述

        // 设置箭头终点在直线的位置 , 根据比例计算出箭头长度
        arrowLength = (int) (len * arrowEndRatio);
        
        // 箭头终点坐标
        int arrowEndX = (int) (startX + arrowLength * Math.cos(angle));
        int arrowEndY = (int) (startY + arrowLength * Math.sin(angle));

最后 , 绘制箭头的两个尾翼 , 箭头的位置 ; 尾翼的起始点 arrowEndX, arrowEndY , 终止点需要根据角度计算出来 ;

在这里插入图片描述

        // 绘制箭头 尾翼 线段 , 直线的角度 增减 45 度 , 即可获得尾翼的角度
        g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle + Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle + Math.PI / 4)));
        g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle - Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle - Math.PI / 4)));

完整代码示例 :

    // 绘制箭头
    private void drawArrow(Graphics g, int startX, int startY, int endX, int endY) {
        // 计算起始点和终止点在 x, y 方向的差值
        int deltaX = endX - startX;
        int deltaY = endY - startY;

        // 计算 直线的角度
        double angle = Math.atan2(deltaY, deltaX);

        // 计算直线的长度
        int len = (int) Math.sqrt(deltaX * deltaX + deltaY * deltaY);

        // 设置箭头终点在直线的位置 , 根据比例计算出箭头长度
        arrowLength = (int) (len * arrowEndRatio);

        // 箭头终点坐标
        int arrowEndX = (int) (endX - arrowLength * Math.cos(angle));
        int arrowEndY = (int) (endY - arrowLength * Math.sin(angle));

        // 绘制箭头 尾翼 线段 , 直线的角度 增减 45 度 , 即可获得尾翼的角度
        g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle + Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle + Math.PI / 4)));
        g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle - Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle - Math.PI / 4)));
    }




二、代码示例



代码示例 :

import java.awt.*;

public class ArrowCanvas extends Canvas {

    /**
     * 起始点 X, Y 坐标
     * 终止点 X, Y 坐标
     */
    private int startX, startY, endX, endY;

    /**
     * 箭头 左右两个尾翼 长度
     */
    private int arrowWingLength = 20;

    /**
     * 箭头终点在直线的位置
     */
    private float arrowEndRatio = 0.5F;

    /**
     * 箭头长度
     */
    private int arrowLength;



    public ArrowCanvas(int startX, int startY, int endX, int endY) {
        this.startX = startX;
        this.startY = startY;
        this.endX = endX;
        this.endY = endY;

        // 设置画布大小
        setSize(400, 400);
    }

    public void paint(Graphics g) {
        // 绘制直线
        g.drawLine(startX, startY, endX, endY);

        // 绘制箭头
        drawArrow(g, startX, startY, endX, endY);
    }

    // 绘制箭头
    private void drawArrow(Graphics g, int startX, int startY, int endX, int endY) {
        // 计算起始点和终止点在 x, y 方向的差值
        int deltaX = endX - startX;
        int deltaY = endY - startY;

        // 计算 直线的角度
        // 返回的是 这条直线 与 x 轴的夹角
        // deltaY / deltaX  是该角度的正切
        // 已知正切值 , 计算角度 , 使用  Math.atan2 函数即可
        // 最终计算的角度是 该直线 与 x 轴夹角
        double angle = Math.atan2(deltaY, deltaX);

        // 计算直线的长度
        int len = (int) Math.sqrt(deltaX * deltaX + deltaY * deltaY);

        // 设置箭头终点在直线的位置 , 根据比例计算出箭头长度
        arrowLength = (int) (len * arrowEndRatio);

        // 箭头终点坐标
        int arrowEndX = (int) (startX + arrowLength * Math.cos(angle));
        int arrowEndY = (int) (startY + arrowLength * Math.sin(angle));

        // 绘制箭头 尾翼 线段 , 直线的角度 增减 45 度 , 即可获得尾翼的角度
        g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle + Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle + Math.PI / 4)));
        g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle - Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle - Math.PI / 4)));
    }

    public static void main(String[] args) {
        // 创建窗口并添加 ArrowCanvas 组件
        Frame f = new Frame("ArrowCanvas Example");
        ArrowCanvas ac = new ArrowCanvas(50, 50, 200, 200);
        f.add(ac);

        // 设置窗口大小并可见
        f.setSize(400, 400);
        f.setVisible(true);
    }
}

执行结果 :

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值