Java Swing绘制箭头

绘制单向箭头、双向箭头

package com.xiangqian.swing;import javax.swing.*;
import java.awt.*;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;/*** 绘制箭头** @author xiangqian* @date 16:00 2019/10/31*/
public class DrawArrow {/*** 绘制面板** @author xiangqian* @date 15:38 2019/11/03*/public static class DrawPanel extends JPanel {private BasicStroke lineStroke;public DrawPanel() {lineStroke = new BasicStroke(2.0f);}@Overrideprotected void paintComponent(Graphics g) {draw((Graphics2D) g);}/*** 绘制** @param g2d*/private void draw(Graphics2D g2d) {Line2D.Double line2D = null;Arrow.Attributes arrowAttributes = null;// 绘制线的“方向1”箭头line2D = new Line2D.Double(120, 100, 300, 300);arrowAttributes = new Arrow.Attributes();drawLineArrowDirection1(g2d, arrowAttributes, line2D);// 绘制线的“方向2”箭头line2D = new Line2D.Double(110, 330, 300, 330);arrowAttributes = new Arrow.Attributes();arrowAttributes.angle = 45;arrowAttributes.height = 80;drawLineArrowDirection2(g2d, arrowAttributes, line2D);// 绘制线的“双向”箭头line2D = new Line2D.Double(500, 200, 260, 200);arrowAttributes = new Arrow.Attributes();arrowAttributes.angle = 30;arrowAttributes.height = 40;drawLineArrowDirectionAll(g2d, arrowAttributes, line2D);}/*** 绘制线的“方向1”箭头** @param g2d* @param arrowAttributes 箭头属性* @param line2D          线*/private void drawLineArrowDirection1(Graphics2D g2d, Arrow.Attributes arrowAttributes, Line2D.Double line2D) {drawLine(g2d, line2D);drawArrow(g2d, arrowAttributes, line2D.getP1(), line2D.getP2());}/*** 绘制线的“方向2”箭头** @param g2d* @param arrowAttributes 箭头属性* @param line2D          线*/private void drawLineArrowDirection2(Graphics2D g2d, Arrow.Attributes arrowAttributes, Line2D.Double line2D) {drawLine(g2d, line2D);drawArrow(g2d, arrowAttributes, line2D.getP2(), line2D.getP1());}/*** 绘制线的“双向”箭头** @param g2d* @param arrowAttributes 箭头属性* @param line2D          线*/private void drawLineArrowDirectionAll(Graphics2D g2d, Arrow.Attributes arrowAttributes, Line2D.Double line2D) {drawLine(g2d, line2D);drawArrow(g2d, arrowAttributes, line2D.getP1(), line2D.getP2());drawArrow(g2d, arrowAttributes, line2D.getP2(), line2D.getP1());}/*** 绘制线** @param g2d* @param line2D*/private void drawLine(Graphics2D g2d, Line2D.Double line2D) {g2d.setColor(Color.BLACK);g2d.setStroke(lineStroke);g2d.draw(line2D);}/*** 绘制箭头** @param g2d* @param arrowAttributes 箭头属性* @param point1          线的第一个点* @param point2          线的第二个点*/private void drawArrow(Graphics2D g2d, Arrow.Attributes arrowAttributes, Point2D point1, Point2D point2) {// 获取Arrow实例Arrow arrow = getArrow(arrowAttributes, point1, point2);// 构建GeneralPathGeneralPath arrow2D = new GeneralPath();arrow2D.moveTo(arrow.point1.x, arrow.point1.y);arrow2D.lineTo(arrow.point2.x, arrow.point2.y);arrow2D.lineTo(arrow.point3.x, arrow.point3.y);arrow2D.closePath();// 绘制g2d.setColor(arrow.attributes.color);g2d.fill(arrow2D);}/*** 获取箭头实体类** @param arrowAttributes 箭头属性* @param point1          线的第一个点* @param point2          线的第二个点* @return*/private Arrow getArrow(Arrow.Attributes arrowAttributes, Point2D point1, Point2D point2) {Arrow arrow = new Arrow(arrowAttributes);// 计算斜边double hypotenuse = arrow.attributes.height / Math.cos(Math.toRadians(arrow.attributes.angle / 2));// 计算当前线所在的象限int quadrant = -1;if (point1.getX() > point2.getX() && point1.getY() < point2.getY()) {quadrant = 1;} else if (point1.getX() < point2.getX() && point1.getY() < point2.getY()) {quadrant = 2;} else if (point1.getX() < point2.getX() && point1.getY() > point2.getY()) {quadrant = 3;} else if (point1.getX() > point2.getX() && point1.getY() > point2.getY()) {quadrant = 4;}// 计算线的夹角double linAngle = getLineAngle(point1.getX(), point1.getY(), point2.getX(), point2.getY());if (Double.isNaN(linAngle)) {// 线与x轴垂直if (point1.getX() == point2.getX()) {if (point1.getY() < point2.getY()) {linAngle = 90;} else {linAngle = 270;}quadrant = 2;}}// 线与y轴垂直else if (linAngle == 0) {if (point1.getY() == point2.getY()) {if (point1.getX() < point2.getX()) {linAngle = 0;} else {linAngle = 180;}quadrant = 2;}}// 上侧一半箭头double xAngle = linAngle - arrow.attributes.angle / 2; // 与x轴夹角double py0 = hypotenuse * Math.sin(Math.toRadians(xAngle)); // 计算y方向增量double px0 = hypotenuse * Math.cos(Math.toRadians(xAngle)); // 计算x方向增量// 下侧一半箭头double yAngle = 90 - linAngle - arrow.attributes.angle / 2; // 与y轴夹角double px1 = hypotenuse * Math.sin(Math.toRadians(yAngle));double py1 = hypotenuse * Math.cos(Math.toRadians(yAngle));// 第一象限if (quadrant == 1) {px0 = -px0;px1 = -px1;} else if (quadrant == 2) {// do nothing} else if (quadrant == 3) {py0 = -py0;py1 = -py1;} else if (quadrant == 4) {py0 = -py0;px0 = -px0;px1 = -px1;py1 = -py1;}// buildarrow.point1 = new Point2D.Double();arrow.point1.x = point1.getX();arrow.point1.y = point1.getY();arrow.point2 = new Point2D.Double();arrow.point2.x = point1.getX() + px0;arrow.point2.y = point1.getY() + py0;arrow.point3 = new Point2D.Double();arrow.point3.x = point1.getX() + px1;arrow.point3.y = point1.getY() + py1;return arrow;}/*** 获取线与X轴的夹角** @param x1* @param y1* @param x2* @param y2* @return*/protected double getLineAngle(double x1, double y1, double x2, double y2) {double k1 = (y2 - y1) / (x2 - x1);double k2 = 0;return Math.abs(Math.toDegrees(Math.atan((k2 - k1) / (1 + k1 * k2))));}}/*** 箭头实体类** @author xiangqian* @date 16:06 2019/10/31*/public static class Arrow {Attributes attributes;Point2D.Double point1;Point2D.Double point2;Point2D.Double point3;public Arrow(Attributes attributes) {this.attributes = attributes;}/*** 箭头属性** @author xiangqian* @date 15:41 2019/11/03*/public static class Attributes {double height; // 箭头的高度double angle; // 箭头角度Color color; // 箭头颜色public Attributes() {this.height = 60;this.angle = 30;this.color = Color.BLACK;}}}public static void main(String[] args) {JFrame frame = new JFrame();frame.setTitle("绘制箭头");Dimension dimension = new Dimension(800, 600);frame.setSize(dimension);frame.setLocationRelativeTo(null);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setContentPane(new DrawPanel());frame.setVisible(true);}}

效果展示

Java Swing绘制箭头相关推荐

  1. 仿金山打字通游戏,模拟键盘(java swing),提示输入,导入本地txt文件

    一.设计思路 1.用一个主窗体,在主窗体上放置两个子窗体,一个是文本面板,一个是模拟键盘面板. 2.文本面板分两个子面板,一个是已有文本,一个是输入文本,在带输入文本面板上添加文件监听器,动态改变下一 ...

  2. java国际象棋棋牌_java使用swing绘制国际象棋棋盘

    本文实例为大家分享了java使用swing绘制国际象棋棋盘的具体代码,供大家参考,具体内容如下 1.完整代码 import java.awt.Color; import java.awt.Point; ...

  3. Java Swing中的聊天气泡

    本文将向您解释"如何在Java swing应用程序中绘制聊天气泡?" 聊天气泡与呼出气泡或思想气泡相同. 今天,大多数聊天应用程序都以这种格式显示转换,因此本文将帮助您在用Java ...

  4. MindFusion教程:Charting for Java Swing中的FunctionSeries

    MindFusion.Diagramming for WinForms是一个能帮助你创建工作流和进程图表的.NET控件:数据库实体关系图表:组织图表:对象层次和关系图表:图表和树.它是基于对象-图表框 ...

  5. python画箭头opencv_OpenCV绘制箭头线

    OpenCV绘制箭头线 可以使用imgproc类的arrowedLine()方法在图像上绘制箭头线. 以下是这种方法的语法 - arrowedLine(Mat img, Point pt1, Poin ...

  6. java swing 聊天气泡_Java Swing中的聊天气泡

    本文将向您解释"如何在Java swing应用程序中绘制聊天气泡?" 聊天气泡与呼出气泡或思想气泡相同. 今天,大多数聊天应用程序都以这种格式显示转换,因此本文将帮助您在用Java ...

  7. 史上最扯Java图形绘制(J2SE)之一JAVA动画效果

    很多主一听说Java界面,一水的头大外带血压高,兄弟我倒觉得没什么必要.           其实Java这东西吧,就简便性和其初衷而言,真他妈就在GUI 这地界是有优势的,单就其2D界面开发的易用性 ...

  8. 客户端是选择Java Swing还是C# Winform

    登录 | 注册 mentat的专栏 目录视图 摘要视图 订阅 [专家问答]韦玮:Python基础编程实战专题     [知识库]Swift资源大集合     [公告]博客新皮肤上线啦     快来领福 ...

  9. java swing 一闪而过_Java代码,为什么图形会一闪而过,怎么修改?

    //未完成:会一闪而过importjava.awt.*;importjava.awt.event.*;importjavax.swing.*;importjava.awt.geom.*;publicc ...

  10. java包裹邮费计算_GitHub - honghailiang/FreightSystem: 基于Java Swing编写的简易运费计算工具...

    FreightSystem 基于java Swing编写的运费计算系统 初始化数据 从excel中读取数据,转化为对象(只保存基础数据:序列号.始发站.目的站.省份.100kg以下(元/kg).100 ...

最新文章

  1. SpringCloud03 Ribbon知识点、 Feign知识点、利用RestTemplate+Ribbon调用远程服务提供的资源、利用feign调用远程服务提供的资源、熔断...
  2. git分支建立删除,打tag
  3. arcengine动态显示所需字段值
  4. android ios 传视频播放器,推荐用于iOS / Android全面格式的视频播放器|手机最强大的播放器...
  5. 【目瞪口呆】通信机房内部长这样
  6. (亲测)躺着破解IDM下载权限,治疗不用破解补丁的强迫症们
  7. word批量转PDF
  8. 基于FPGA打地鼠游戏的设计与实现
  9. 【时间与空间】基本概念
  10. Pick peaks
  11. flutter开发的即时聊天应用
  12. 数据分析师必须掌握的模型——AARRR漏斗模型
  13. 2020复旦机试题:斗牛
  14. seosem是什么意思?
  15. 【JAVA】7-1 厘米换算英尺英寸
  16. NAND、NOR、FLASH、Memory
  17. 干货!如何在SCI论文中转述和总结别人的论文和成果
  18. qq登录测试用例(功能性测试、登录界面、性能、安全性、可用性、兼容性)
  19. linux 根文件系统满了,Solaris 10下根文件系统满的处理方法
  20. 移动互联网应用技术架构简介-Restful服务

热门文章

  1. 嚼一嚼 class 文件结构
  2. 金万维未找到服务器信息,域名解析失败原因和问题排查方法
  3. 基于SSM的医院管理系统
  4. Java实现 LeetCode 506 相对名次
  5. 『C++』endl、ends和flush的区别
  6. Libero Soc v11.9的安装以及证书的获取(2021新版)
  7. SuperMap iServer产品版本以及模块介绍
  8. JZOJ【NOI2017模拟3.30】原谅
  9. 【网页设计自习室#004】网页页面导航栏(header头部)的设计
  10. 如何使用Redis Streams