JavaFX Canvas: 填充由多个几何图形组成的闭合路径
JavaFX Canvas: fill closed path composed of multiple geometries
我想绘制并填充一条由 2 条弧线和 2 条线组成的具有特定颜色的路径。我需要使用 JavaFX 中的 Canvas,因为我需要绘制更多内容。问题是,我创建的路径甚至没有绘制或填充。我要的是这个
但我的代码生成了这个
您可能会注意到,此弧在左侧和右侧比在中间更细。不幸的是,仅使用具有 ceratin 笔划宽度的简单弧线对我来说不是一个选择。
这是我的代码,其中注释部分生成第二张图片。我已经尝试使用绘制路径工具并填充它,但它不起作用
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.shape.ArcType;
import javafx.stage.Stage;
public final class CanvasTest extends Application {
private static final int WIDTH = 400;
private static final int HEIGHT = 300;
private static final int RADIUS = 250;
private static final int BRICK_HEIGHT = 15;
private static final int RADIUSHALF = RADIUS / 2;
private static GraphicsContext gc;
@Override
public void start(Stage stage) {
final Group root = new Group();
final Scene scene = new Scene(root, WIDTH, HEIGHT);
final Canvas can = new Canvas(WIDTH, HEIGHT);
gc = can.getGraphicsContext2D();
gc.setFill(Color.BLACK);
gc.fillRect(0, 0, WIDTH, HEIGHT);
drawArc(WIDTH / 2, HEIGHT / 2);
root.getChildren().add(can);
stage.setScene(scene);
stage.show();
}
private void drawArc(final int posX, final int posY) {
gc.setStroke(Color.WHITE);
gc.setLineWidth(1);
gc.setFill(Color.WHITE);
final double newRadius = RADIUSHALF - BRICK_HEIGHT;
final double yOffsetLowerArc = Math.cos(Math.toRadians(45)) * newRadius;
final double xOffsetLowerArc = Math.sin(Math.toRadians(45)) * newRadius;
final double newAngleLowerArc = Math.toDegrees(Math.atan2(xOffsetLowerArc, yOffsetLowerArc + BRICK_HEIGHT));
final double xOffsetUpperArc = Math.cos(Math.toRadians(45)) * RADIUSHALF;
final double yOffsetUpperArc = Math.sin(Math.toRadians(45)) * RADIUSHALF;
final double yOffsetNewLowerArc = Math.cos(Math.toRadians(newAngleLowerArc)) * RADIUSHALF;
final double xOffsetNewLowerArc = Math.sin(Math.toRadians(newAngleLowerArc)) * RADIUSHALF;
// this code produces the un-filled custom arc
// gc.strokeArc(posX - RADIUSHALF, posY - RADIUSHALF, RADIUS, RADIUS, 45, 90, ArcType.OPEN);
// gc.strokeArc(posX - RADIUSHALF, posY - RADIUSHALF + BRICK_HEIGHT, RADIUS, RADIUS, 90 - newAngleLowerArc, 2 * newAngleLowerArc, ArcType.OPEN);
// gc.strokeLine(posX - xOffsetNewLowerArc, posY + BRICK_HEIGHT - yOffsetNewLowerArc, posX - xOffsetUpperArc, posY - yOffsetUpperArc);
// gc.strokeLine(posX + xOffsetNewLowerArc, posY + BRICK_HEIGHT - yOffsetNewLowerArc, posX + xOffsetUpperArc, posY - yOffsetUpperArc);
gc.beginPath();
gc.arc(posX - RADIUSHALF, posY - RADIUSHALF, RADIUS, RADIUS, 45, 90/*, ArcType.OPEN*/);
gc.arc(posX - RADIUSHALF, posY - RADIUSHALF + BRICK_HEIGHT, RADIUS, RADIUS, 90 - newAngleLowerArc, 2 * newAngleLowerArc/*, ArcType.OPEN*/);
gc.moveTo(posX + xOffsetNewLowerArc, posY + BRICK_HEIGHT - yOffsetNewLowerArc);
gc.lineTo(posX + xOffsetUpperArc, posY - yOffsetUpperArc);
gc.moveTo(posX - xOffsetNewLowerArc, posY + BRICK_HEIGHT - yOffsetNewLowerArc);
gc.lineTo(posX - xOffsetUpperArc, posY - yOffsetUpperArc);
gc.closePath();
gc.fill();
}
public static void main(String[] args) {
Application.launch(args);
}
}
也许我也误解了 JavaFX 中路径的概念,但对我来说我的方法是合理的 :-) 无论如何它都不起作用。 (我也看了这个“Working with Canvas”)
您的代码存在一些问题。 GraphicsContext.arc
are not the same as GraphicsContext.strokeArc
.
的参数
strokeArc(double x,
double y,
double w,
double h,
double startAngle,
double arcExtent,
ArcType closure)
arc(double centerX,
double centerY,
double radiusX,
double radiusY,
double startAngle,
double length)
不同之处在于:strokeArc
在给定 width
和 height
的点 (x, y)
处的矩形中绘制作为椭圆的一部分的圆弧。然而,arc
构建了一条路径,该路径是椭圆形的一部分,以 (centerX, centerY)
为中心,半径为 radiusX
和 radiusY
。要获得 arc
的适当参数,您可以使用以下公式:
centerX = (x+w)/2
centerY = (y+h)/2
radiusX = w/2
radiusY = h/2
此外,您无需调用 moveTo
来构建路径。 2 条弧足以构建路径。还要确保使用不同方向的弧线(顺时针方向和逆时针方向)连接弧线的最近端:
gc.beginPath();
gc.arc(posX, posY, RADIUSHALF, RADIUSHALF, 45, 90);
// next arc in opposite direction
gc.arc(posX, posY + BRICK_HEIGHT, RADIUSHALF, RADIUSHALF, 90 + newAngleLowerArc, -2 * newAngleLowerArc);
gc.closePath();
gc.fill();
我想绘制并填充一条由 2 条弧线和 2 条线组成的具有特定颜色的路径。我需要使用 JavaFX 中的 Canvas,因为我需要绘制更多内容。问题是,我创建的路径甚至没有绘制或填充。我要的是这个
但我的代码生成了这个
您可能会注意到,此弧在左侧和右侧比在中间更细。不幸的是,仅使用具有 ceratin 笔划宽度的简单弧线对我来说不是一个选择。
这是我的代码,其中注释部分生成第二张图片。我已经尝试使用绘制路径工具并填充它,但它不起作用
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.shape.ArcType;
import javafx.stage.Stage;
public final class CanvasTest extends Application {
private static final int WIDTH = 400;
private static final int HEIGHT = 300;
private static final int RADIUS = 250;
private static final int BRICK_HEIGHT = 15;
private static final int RADIUSHALF = RADIUS / 2;
private static GraphicsContext gc;
@Override
public void start(Stage stage) {
final Group root = new Group();
final Scene scene = new Scene(root, WIDTH, HEIGHT);
final Canvas can = new Canvas(WIDTH, HEIGHT);
gc = can.getGraphicsContext2D();
gc.setFill(Color.BLACK);
gc.fillRect(0, 0, WIDTH, HEIGHT);
drawArc(WIDTH / 2, HEIGHT / 2);
root.getChildren().add(can);
stage.setScene(scene);
stage.show();
}
private void drawArc(final int posX, final int posY) {
gc.setStroke(Color.WHITE);
gc.setLineWidth(1);
gc.setFill(Color.WHITE);
final double newRadius = RADIUSHALF - BRICK_HEIGHT;
final double yOffsetLowerArc = Math.cos(Math.toRadians(45)) * newRadius;
final double xOffsetLowerArc = Math.sin(Math.toRadians(45)) * newRadius;
final double newAngleLowerArc = Math.toDegrees(Math.atan2(xOffsetLowerArc, yOffsetLowerArc + BRICK_HEIGHT));
final double xOffsetUpperArc = Math.cos(Math.toRadians(45)) * RADIUSHALF;
final double yOffsetUpperArc = Math.sin(Math.toRadians(45)) * RADIUSHALF;
final double yOffsetNewLowerArc = Math.cos(Math.toRadians(newAngleLowerArc)) * RADIUSHALF;
final double xOffsetNewLowerArc = Math.sin(Math.toRadians(newAngleLowerArc)) * RADIUSHALF;
// this code produces the un-filled custom arc
// gc.strokeArc(posX - RADIUSHALF, posY - RADIUSHALF, RADIUS, RADIUS, 45, 90, ArcType.OPEN);
// gc.strokeArc(posX - RADIUSHALF, posY - RADIUSHALF + BRICK_HEIGHT, RADIUS, RADIUS, 90 - newAngleLowerArc, 2 * newAngleLowerArc, ArcType.OPEN);
// gc.strokeLine(posX - xOffsetNewLowerArc, posY + BRICK_HEIGHT - yOffsetNewLowerArc, posX - xOffsetUpperArc, posY - yOffsetUpperArc);
// gc.strokeLine(posX + xOffsetNewLowerArc, posY + BRICK_HEIGHT - yOffsetNewLowerArc, posX + xOffsetUpperArc, posY - yOffsetUpperArc);
gc.beginPath();
gc.arc(posX - RADIUSHALF, posY - RADIUSHALF, RADIUS, RADIUS, 45, 90/*, ArcType.OPEN*/);
gc.arc(posX - RADIUSHALF, posY - RADIUSHALF + BRICK_HEIGHT, RADIUS, RADIUS, 90 - newAngleLowerArc, 2 * newAngleLowerArc/*, ArcType.OPEN*/);
gc.moveTo(posX + xOffsetNewLowerArc, posY + BRICK_HEIGHT - yOffsetNewLowerArc);
gc.lineTo(posX + xOffsetUpperArc, posY - yOffsetUpperArc);
gc.moveTo(posX - xOffsetNewLowerArc, posY + BRICK_HEIGHT - yOffsetNewLowerArc);
gc.lineTo(posX - xOffsetUpperArc, posY - yOffsetUpperArc);
gc.closePath();
gc.fill();
}
public static void main(String[] args) {
Application.launch(args);
}
}
也许我也误解了 JavaFX 中路径的概念,但对我来说我的方法是合理的 :-) 无论如何它都不起作用。 (我也看了这个“Working with Canvas”)
您的代码存在一些问题。 GraphicsContext.arc
are not the same as GraphicsContext.strokeArc
.
strokeArc(double x,
double y,
double w,
double h,
double startAngle,
double arcExtent,
ArcType closure)
arc(double centerX,
double centerY,
double radiusX,
double radiusY,
double startAngle,
double length)
不同之处在于:strokeArc
在给定 width
和 height
的点 (x, y)
处的矩形中绘制作为椭圆的一部分的圆弧。然而,arc
构建了一条路径,该路径是椭圆形的一部分,以 (centerX, centerY)
为中心,半径为 radiusX
和 radiusY
。要获得 arc
的适当参数,您可以使用以下公式:
centerX = (x+w)/2
centerY = (y+h)/2
radiusX = w/2
radiusY = h/2
此外,您无需调用 moveTo
来构建路径。 2 条弧足以构建路径。还要确保使用不同方向的弧线(顺时针方向和逆时针方向)连接弧线的最近端:
gc.beginPath();
gc.arc(posX, posY, RADIUSHALF, RADIUSHALF, 45, 90);
// next arc in opposite direction
gc.arc(posX, posY + BRICK_HEIGHT, RADIUSHALF, RADIUSHALF, 90 + newAngleLowerArc, -2 * newAngleLowerArc);
gc.closePath();
gc.fill();