如果折线中的段处于特定角度,则在折线中的段之间绘制斜角。如果您正在绘制一条恰好在具有特定颜色的其他像素附近绘制的线,则它没有关系 - 一旦您绘制了矩形,图形对象就不知道矩形,它(实际上)仅保存像素。(或者更确切地说,图像或操作系统窗口保存像素)。
要绘制一个简单的箭头,请像您正在做的那样为茎绘制一条线,然后为V形绘制一条折线。看起来更好看的箭头有弯曲的边并被填充。
您可能不想使用斜角作为箭头,因为斜面是平坦的;而是使用斜接选项:
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
public class BevelArrows
{
public static void main ( String...args )
{
SwingUtilities.invokeLater ( new Runnable () {
BevelArrows arrows = new BevelArrows();
@Override
public void run () {
JFrame frame = new JFrame ( "Bevel Arrows" );
frame.add ( new JPanel() {
public void paintComponent ( Graphics g ) {
arrows.draw ( ( Graphics2D ) g, getWidth(), getHeight() );
}
}
, BorderLayout.CENTER );
frame.setSize ( 800, 400 );
frame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
frame.setVisible ( true );
}
} );
}
interface Arrow {
void draw ( Graphics2D g );
}
Arrow[] arrows = { new LineArrow(), new CurvedArrow() };
void draw ( Graphics2D g, int width, int height )
{
g.setRenderingHint ( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
g.setColor ( Color.WHITE );
g.fillRect ( 0, 0, width, height );
for ( Arrow arrow : arrows ) {
g.setColor ( Color.ORANGE );
g.fillRect ( 350, 20, 20, 280 );
g.setStroke ( new BasicStroke ( 20.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL ) );
g.translate ( 0, 60 );
arrow.draw ( g );
g.setStroke ( new BasicStroke ( 20.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER ) );
g.translate ( 0, 100 );
arrow.draw ( g );
g.setStroke ( new BasicStroke ( 20.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND ) );
g.translate ( 0, 100 );
arrow.draw ( g );
g.translate ( 400, -260 );
}
}
static class LineArrow implements Arrow
{
public void draw ( Graphics2D g )
{
float arrowRatio = 0.5f;
float arrowLength = 80.0f;
BasicStroke stroke = ( BasicStroke ) g.getStroke();
float endX = 350.0f;
float veeX;
switch ( stroke.getLineJoin() ) {
case BasicStroke.JOIN_BEVEL:
veeX = endX - stroke.getLineWidth() * 0.25f;
break;
default:
case BasicStroke.JOIN_MITER:
veeX = endX - stroke.getLineWidth() * 0.5f / arrowRatio;
break;
case BasicStroke.JOIN_ROUND:
veeX = endX - stroke.getLineWidth() * 0.5f;
break;
}
Path2D.Float path = new Path2D.Float();
path.moveTo ( veeX - arrowLength, -arrowRatio*arrowLength );
path.lineTo ( veeX, 0.0f );
path.lineTo ( veeX - arrowLength, arrowRatio*arrowLength );
g.setColor ( Color.BLUE );
g.draw ( path );
g.setColor ( Color.YELLOW );
g.draw ( new Line2D.Float ( 50.0f, 0.0f, veeX, 0.0f ) );
g.setColor ( Color.RED );
g.draw ( new Line2D.Float ( 50.0f, 0.0f, veeX - stroke.getLineWidth() * 0.25f, 0.0f ) );
}
}
static class CurvedArrow implements Arrow
{
public void draw ( Graphics2D g )
{
float arrowRatio = 0.5f;
float arrowLength = 80.0f;
BasicStroke stroke = ( BasicStroke ) g.getStroke();
float endX = 350.0f;
float veeX = endX - stroke.getLineWidth() * 0.5f / arrowRatio;
Path2D.Float path = new Path2D.Float();
float waisting = 0.5f;
float waistX = endX - arrowLength * 0.5f;
float waistY = arrowRatio * arrowLength * 0.5f * waisting;
float arrowWidth = arrowRatio * arrowLength;
path.moveTo ( veeX - arrowLength, -arrowWidth );
path.quadTo ( waistX, -waistY, endX, 0.0f );
path.quadTo ( waistX, waistY, veeX - arrowLength, arrowWidth );
path.lineTo ( veeX - arrowLength * 0.75f, 0.0f );
path.lineTo ( veeX - arrowLength, -arrowWidth );
g.setColor ( Color.BLUE );
g.fill ( path );
g.setColor ( Color.RED );
g.draw ( new Line2D.Float ( 50.0f, 0.0f, veeX - arrowLength * 0.5f, 0.0f ) );
}
}
}