如何在Canvas上的SWT中绘制带箭头的线条

时间:2015-12-08 14:56:35

标签: java swt awt drawing

我想用箭头画一条线。该线可以有任何角度。如何在SWT中实现它?

我在AWT发现了类似的帖子。我想将其转换为SWT。但是面临将以下方法转换为SWT的问题。特别是在以下行:

at.concatenate(AffineTransform.getRotateInstance(angle));

以下是this post

的方法
void drawArrow(Graphics g1, int x1, int y1, int x2, int y2) {
  Graphics2D g = (Graphics2D) g1.create();
  double dx = x2 - x1, dy = y2 - y1;
  double angle = Math.atan2(dy, dx);
  int len = (int) Math.sqrt(dx*dx + dy*dy);
  AffineTransform at = AffineTransform.getTranslateInstance(x1, y1);
  at.concatenate(AffineTransform.getRotateInstance(angle));
  g.transform(at);

  // Draw horizontal arrow starting in (0, 0)
  g.drawLine(0, 0, len, 0);
  g.fillPolygon(new int[] {len, len-ARR_SIZE, len-ARR_SIZE, len}, new int[] {0, -ARR_SIZE, ARR_SIZE, 0}, 4);
}

2 个答案:

答案 0 :(得分:1)

这里,箭头方向是从线的方向计算的。我还为该线添加了偏移量,因此它没有通过箭头。行程宽度越高,这一点就越明显。

public static void drawArrow(GC gc, int x1, int y1, int x2, int y2, double arrowLength, double arrowAngle) {
    double theta = Math.atan2(y2 - y1, x2 - x1);
    double offset = (arrowLength - 2) * Math.cos(arrowAngle);

    gc.drawLine(x1, y1, (int)(x2 - offset * Math.cos(theta)), (int)(y2 - offset * Math.sin(theta)));

    Path path = new Path(gc.getDevice());
    path.moveTo((float)(x2 - arrowLength * Math.cos(theta - arrowAngle)), (float)(y2 - arrowLength * Math.sin(theta - arrowAngle)));
    path.lineTo((float)x2, (float)y2);
    path.lineTo((float)(x2 - arrowLength * Math.cos(theta + arrowAngle)), (float)(y2 - arrowLength * Math.sin(theta + arrowAngle)));
    path.close();

    gc.fillPath(path);

    path.dispose();
}

...

gc.setLineWidth(1);
gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK));
gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
drawArrow(gc, x1, y1, x2, y2, 8, Math.toRadians(40));

答案 1 :(得分:0)

转换为SWT的答案given here如下所示:

static Path createArrowForLine( Device device, Point fromPoint, double rotationDeg, double length, double wingsAngleDeg ) {
  double ax = fromPoint.x;
  double ay = fromPoint.y;
  double radB = Math.toRadians( -rotationDeg + wingsAngleDeg );
  double radC = Math.toRadians( -rotationDeg - wingsAngleDeg );
  Path resultPath = new Path( device );
  resultPath.moveTo( ( float )( length * Math.cos( radB ) + ax ), ( float )( length * Math.sin( radB ) + ay ) );
  resultPath.lineTo( ( float )ax, ( float )ay );
  resultPath.lineTo( ( float )( length * Math.cos( radC ) + ax ), ( float )( length * Math.sin( radC ) + ay ) );
  return resultPath;
}

SWT Path API使用float而不是double s,因此使用强制转换。

要使用上述方法在画布上绘制箭头,您可以使用以下代码:

Canvas canvas = new Canvas( parent, SWT.NONE );
shell.addPaintListener( new PaintListener() {
  @Override
  public void paintControl( PaintEvent event ) {
    event.gc.setBackground( event.display.getSystemColor( SWT.COLOR_RED ) );
    Path path = createArrowForLine( event.display, new Point( 100, 100 ), 180, 100, 45 );
    event.gc.fillPath( path );
    path.dispose();
  }
} );