【问题标题】:Can I apply 2D transforms to shapes on a JavaFX 8 Canvas?我可以对 JavaFX 8 Canvas 上的形状应用 2D 变换吗?
【发布时间】:2015-08-28 16:46:18
【问题描述】:

我正在将之前在 Swing 中完成的一个类移植到 JavaFX 8。它显示了一个 UI 元素,该元素看起来像一个模拟电压表,其中有一个半圆,并定期被一组“tic 标记”包围。在 Swing 版本中,该类是 JPanel 的扩展,并且在paintComponent(Graphics g) 中绘制的tic 标记如下:

private Line2D ticLine = new Line2D.Float(0, LINE_ROOT_Y, TIC_LENGTH, LINE_ROOT_Y);

public void paintComponent(Graphics g)
   {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;

      // Draw tic marks
      if (ticCount > 0)
      {
         g2.draw(ticLine); // First tic

         AffineTransform ticTrans = new AffineTransform();
         // Draw all additional tics rotated around half circle
         for (int i = 1; i < ticCount; i++)
         {
            ticTrans.rotate(Math.toRadians(ticGap),
                 METER_MIDDLE, METER_BASE_Y);
            g2.draw(ticTrans.createTransformedShape(ticLine));
         }
      }
   }

这很好。

现在有了 JavaFX,我正在使用扩展 VBox 的类。它包含 2 个堆叠的 Canvas 对象。其中一个将绘制静态元素,如半圆和 tic 标记,另一个用于定期移动的米线。在第一个 Canvas 上,我希望使用与在 Swing 版本中类似的循环来轻松重绘第一个 ticCount # 在半圆周围的附加位置中的第一个 tic 标记。所以我尝试了以下编译并运行但只绘制了第一个 tic 标记:

// Called from the constructor:
MeterGC = MeterCanvas.getGraphicsContext2D();
Line ticLine = new Line(0, LINE_ROOT_Y, TIC_LENGTH, LINE_ROOT_Y);

// Draw tic marks
if (ticCount > 1)
{
   MeterGC.setStroke(Color.GRAY);
   MeterGC.setLineWidth(BASIC_LINE_WIDTH);
   MeterGC.strokeLine(ticLine.getStartX(), ticLine.getStartY(), 
                      ticLine.getEndX(), ticLine.getEndY());

   Rotate ticTrans = new Rotate(Math.toRadians(ticGap), METER_MIDDLE, METER_BASE_Y);
   for (int i = 1; i < ticCount; i++)
   {
      ticLine.getTransforms().add(ticTrans);
      MeterGC.strokeLine(ticLine.getStartX(), ticLine.getStartY(), 
                         ticLine.getEndX(), ticLine.getEndY());
    }
}

尝试像这样转换 Shape 对象可能只在绘制到场景而不是在画布上时有效。或者我必须在“ticLine.getTransforms().add(ticTrans)”行之后做一些事情来让它们应用于该行。我至少接近了吗?还是有更好的方法来做我在这里尝试的事情?

【问题讨论】:

    标签: java javafx javafx-8


    【解决方案1】:

    你做错了什么

    在您的示例代码中,您将转换应用于 Line 对象(您从未显示)。

    如何解决

    您需要set the transform on the canvas GraphicsContext 才能在画布上划线。

    示例代码

    例如,请参阅:


    /**
     * Sets the transform for the GraphicsContext to rotate around a pivot point.
     *
     * @param gc the graphics context the transform to applied to.
     * @param angle the angle of rotation.
     * @param px the x pivot co-ordinate for the rotation (in canvas co-ordinates).
     * @param py the y pivot co-ordinate for the rotation (in canvas co-ordinates).
     */
    private void rotate(GraphicsContext gc, double angle, double px, double py) {
        Rotate r = new Rotate(angle, px, py);
        gc.setTransform(r.getMxx(), r.getMyx(), r.getMxy(), r.getMyy(), r.getTx(), r.getTy());
    }
    

    【讨论】:

    • 这也有助于注意到在计算旋转时不再需要 Math.toRadians()。该代码适用于以下 for 循环: for (int i = 1; i
    • 迈克,您可以self-answer your question 使用您用来解决问题的代码。答案中的代码可以格式化,并且比内联 cmets 代码更易于阅读。
    【解决方案2】:

    这是我修改后的 for 循环,它运行良好。注意到在 JavaFX 中不再需要将 Rotate 中的角度转换为弧度也是使其正常工作的关键。

    for (int i = 1; i < ticCount; i++)
    {
       Rotate ticTrans = new Rotate(ticGap * i, METER_MIDDLE, METER_BASE_Y);
       MeterGC.setTransform(ticTrans.getMxx(), ticTrans.getMyx(), ticTrans.getMxy(),
                            ticTrans.getMyy(), ticTrans.getTx(), ticTrans.getTy());
       MeterGC.strokeLine(ticLine.getStartX(), ticLine.getStartY(), 
                          ticLine.getEndX(), ticLine.getEndY());
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-14
      • 1970-01-01
      • 2021-06-23
      相关资源
      最近更新 更多