最近需要用到java带箭头的直线,在网上搜了一下,这里主要是来自网上,自己添加了箭头随鼠标的移动而改变的功能。自己还一直没有理解是怎么计算箭头的坐标的。看来高中学的几何知识都搞忘咯。不说这些了,先来看一看运行的效果。
具体代码如下:
package com.mengke.j2se.scpture;
import java.awt.*;
import javax.swing.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.*;
class ArrowLinePanel extends JPanel implements MouseMotionListener,MouseListener{
// confirm the line position
private int x1 = 0;
private int y1 = 0;
private int x2 = 0;
private int y2 = 0;
public ArrowLinePanel() {
setBackground(Color.white);
addMouseListener(this);
addMouseMotionListener(this);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(Color.black);
drawAL(x1, y1, x2, y2, g2);// 这里x1, y1, x2, y2必须要声明并且初始化,而具体声明的位置和初始化的值
}
public static void drawAL(int sx, int sy, int ex, int ey, Graphics2D g2)
{
double H = 10; // 箭头高度
double L = 4; // 底边的一半
int x3 = 0;
int y3 = 0;
int x4 = 0;
int y4 = 0;
double awrad = Math.atan(L / H); // 箭头角度
double arraow_len = Math.sqrt(L * L + H * H); // 箭头的长度
double[] arrXY_1 = rotateVec(ex - sx, ey - sy, awrad, true, arraow_len);
double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len);
double x_3 = ex - arrXY_1[0]; // (x3,y3)是第一端点
double y_3 = ey - arrXY_1[1];
double x_4 = ex - arrXY_2[0]; // (x4,y4)是第二端点
double y_4 = ey - arrXY_2[1];
Double X3 = new Double(x_3);
x3 = X3.intValue();
Double Y3 = new Double(y_3);
y3 = Y3.intValue();
Double X4 = new Double(x_4);
x4 = X4.intValue();
Double Y4 = new Double(y_4);
y4 = Y4.intValue();
// 画线
g2.drawLine(sx, sy, ex, ey);
//
GeneralPath triangle = new GeneralPath();
triangle.moveTo(ex, ey);
triangle.lineTo(x3, y3);
triangle.lineTo(x4, y4);
triangle.closePath();
//实心箭头
g2.fill(triangle);
//非实心箭头
//g2.draw(triangle);
}
// 计算
public static double[] rotateVec(int px, int py, double ang,
boolean isChLen, double newLen) {
double mathstr[] = new double[2];
// 矢量旋转函数,参数含义分别是x分量、y分量、旋转角、是否改变长度、新长度
double vx = px * Math.cos(ang) - py * Math.sin(ang);
double vy = px * Math.sin(ang) + py * Math.cos(ang);
if (isChLen) {
double d = Math.sqrt(vx * vx + vy * vy);
vx = vx / d * newLen;
vy = vy / d * newLen;
mathstr[0] = vx;
mathstr[1] = vy;
}
return mathstr;
}
@Override
public void mouseDragged(MouseEvent e) {
//改变箭头的坐标
x2 = e.getX();
y2 = e.getY();
repaint();
}
@Override
public void mouseMoved(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
//设置箭头的起始坐标
x1 = e.getX();
y1 = e.getY();
}
@Override
public void mouseReleased(MouseEvent e) {
}
}
测试类:
package com.mengke.j2se.scpture;
public class DrawFrame extends JFrame {
// 活动图窗口大小
public static final int DEFAULT_WIDTH = 1000;
public static final int DEFAULT_HEIGHT = 800;
public DrawFrame() {
setTitle("Activity Diagram");
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
ArrowLinePanel panel = new ArrowLinePanel();
add(panel);
}
public static void main(String args[]) {
DrawFrame frame = new DrawFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
}