【问题标题】:How to draw a line with arrow in SWT on Canvas如何在 Canvas 上的 SWT 中绘制带箭头的线
【发布时间】:2016-04-10 18:34:55
【问题描述】:

我想用箭头画一条线。线可以有任何角度。如何在 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);
}

【问题讨论】:

标签: java swt awt drawing


【解决方案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));

【讨论】:

    【解决方案2】:

    答案given here 翻译成 SWT 如下所示:

    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 路径 API 使用 floats 而不是 doubles,因此使用了强制转换。

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

    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();
      }
    } );
    

    【讨论】:

    • 我需要动态旋转变换,以便将箭头三角形正确绘制在直线上。我需要将问题中链接中接受的答案转换为 SWT。
    • 使用rotationDeg 参数,可以旋转箭头。这不是你要找的吗?
    • 不,该方法应采用 fromPoint 和 toPoint 2 个点的坐标。输出是带箭头的有向线。我的问题中描述的链接的接受答案就是这样做的。
    • 请注意Path扩展 Resource,因此必须被处理掉。在PaintListener中使用这个方法会很快分配很多句柄。
    猜你喜欢
    • 2011-09-28
    • 1970-01-01
    • 2014-08-06
    • 2019-12-13
    • 1970-01-01
    • 2018-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多