如何扩展 JavaFX Shape 类以实现自定义形状
Posted
技术标签:
【中文标题】如何扩展 JavaFX Shape 类以实现自定义形状【英文标题】:How to extend the JavaFX Shape class to implement custom shapes 【发布时间】:2016-07-05 06:35:24 【问题描述】:我正在开发一个应用程序来为某些特定问题的二维几何建模。当然,我想在屏幕上绘制那个几何图形,让用户真正看到它。
JavaFX 有一些 2D 形状,如矩形、椭圆等。它也有三次和四次曲线,实现为贝塞尔曲线。搜索自定义形状并没有帮助,因为我发现的只是一些示例,例如获取一些形状元素(例如路径)并将它们组合在一起以绘制自定义形状,例如心形或钻石。搜索有关如何通过扩展 Shape 类来实现新形状的信息就更没用了。
我要绘制的是任意顺序和长度的 B 样条曲线。我知道如何计算和实现样条线本身,但我不知道如何将它们实现为新形状或形状包装器。
我查看了JavaFX的源代码和纪录片。似乎这些形状本身就是某种包装类。例如。 Ellipse 类包含一个椭圆作为成员,它是几何包的一部分。这个递归走得很远。
现在JavaFX必须使用某种方法来实际绘制曲线,但我找不到。
那么我如何扩展 JavaFX 形状以创建例如样条类? Java绘制它的关键是什么方法/类?
我希望有人可以帮助我。
您真诚的托尔斯滕
【问题讨论】:
你能更详细地解释一下为什么Path(它扩展了Shape)还不够吗? 我不认为你将能够直接扩展 Shape 并在不依赖标记的 API 的情况下渲染扩展的形状:“@deprecated 这是一个不打算使用的内部 API,将在下一个版本中删除”。 @VGR 使用路径我只需将不同的形状组合成一个。这将我限制在标准形状类中。所以,例如,我只能画到四度的曲线。对于没有预构建类的所有内容,我必须使用预构建形状类创建该曲线,并将曲线和线段放在一起以创建和近似。 【参考方案1】:我会看看JSilhoutte 是如何实现它们的形状的。
例如,Cross
不会扩展 Shape
,但它通过创建两个矩形并使用 Shape.union
组合它们来生成一个代表十字的 Shape
。下面是相关方法:
@Override
protected void calculateShape()
double cx = getCenterX();
double cy = getCenterY();
double r = getRadius();
double n = validateRoundness(getRoundness());
double w = validateWidth(getWidth(), r);
double arcWH = w * n;
Rectangle beam1 = new Rectangle(cx - r, cy - (w / 2), r * 2, w);
Rectangle beam2 = new Rectangle(cx - (w / 2), cy - r, w, r * 2);
beam1.setArcWidth(arcWH);
beam1.setArcHeight(arcWH);
beam2.setArcWidth(arcWH);
beam2.setArcHeight(arcWH);
Shape shape = Shape.union(beam1, beam2);
shape.getStyleClass().addAll("silhouette", "silhoutte-cross");
setShape(shape);
因此,您可以使用 Shape.union
将多个 CubicCurve
/QuadCurve
形状组合在一起,以创建任意顺序和长度的 B 样条曲线。
【讨论】:
【参考方案2】:我试图做类似的事情,但我没有尝试扩展 Shape,而是尝试扩展 PathElement。我这样做是为了实现一个 nurbsTo 方法,该方法允许我绘制 NURBS 或 B 样条曲线。 PathElement 是一个希望你重写的抽象类:
void addTo(NGPath)
它不是公开的,所以如果你想这样做,你的新类必须在 javafx/scene/shape 包中。所以基本上,你不能那样做。看到这篇文章,我快速查看了编写一个扩展形状的调用是否可行,正如 Thorsten 正确指出的那样,这看起来像是一条艰难的尝试下去的道路,所以我没有追求它。
我采用的方法是让我的 NURBS 类生成一组 MoveTo 命令。我以足够的增量值迭代 U(t) 以获得足够的点,使曲线看起来平滑。这可能是满足 Thorsen 发布需求的最合理方式。如果您查看类似 Circle 的 javafx 实现,那么它在内部也在做同样的事情。默认情况下,Circle 类在圆形上计算 64 个点并绘制线条。对于大多数 NURBS 和 B-Spline 曲线,我发现 100 个点看起来既漂亮又平滑,但这当然取决于所使用的度数、控制点和节点。
【讨论】:
最后,所有非平凡的弯曲几何图形在渲染之前都会被展平为线性线段。 参见:“com.sun.javafx.geom.FlateningPathIterator”。 是的,当然,您在渲染之前将不平凡的曲线变平。这就是您必须做的事情,因为 JavaFX 图形功能使得几乎不可能扩展 PathElement 或开发新的自定义形状。发布的问题是“你如何扩展 Shape?”,我建议不要这样做并采用扁平曲线方法。 FlattenPathIterator 没有用,因为您无法制作自定义 PathElement。以上是关于如何扩展 JavaFX Shape 类以实现自定义形状的主要内容,如果未能解决你的问题,请参考以下文章