我正在开发一个个人项目,我希望用户能够使用简单版本的径向菜单。我一直在尝试创建一个由 N 个弧(或其他形状)组成的戒指,我希望它看起来类似于甜甜圈/戒指。其中件数以及内半径和外半径可以使用变量进行配置。
我有一些部分工作但看起来很粗糙的东西。这是我迄今为止最好的。下面我附上了我的代码和结果的屏幕截图。我希望每块都围绕内圆大小相等
另请注意,我看到其他帖子利用增加弧线的宽度,我宁愿不使用它,因为我遇到了鼠标悬停在侦听器上的问题,其中“命中区域”有点偏离。
package com.example.javafx21;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.stage.Stage;
public class HelloApplication extends Application {
@Override
public void start(Stage primaryStage) {
Pane root = new Pane();
root.setPrefSize(300, 300);
double centerX = 150;
double centerY = 150;
double innerRadius = 40;
double outerRadius = 100;
int numPieces = 8;
for (int i = 0; i < numPieces; i++) {
double angle = 360.0 / numPieces * i;
Arc arc = new Arc();
arc.setCenterX(centerX);
arc.setCenterY(centerY);
arc.setRadiusX(outerRadius);
arc.setRadiusY(outerRadius);
arc.setStartAngle(angle);
arc.setLength((double) 360 / numPieces);
arc.setType(ArcType.OPEN);
arc.setStroke(Color.color(Math.random(), Math.random(), Math.random()));
arc.setStrokeWidth(outerRadius - innerRadius);
arc.setFill(null);
root.getChildren().add(arc);
}
Scene scene = new Scene(root);
primaryStage.setTitle("Adjustable Radius Semi-Rings");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
这里是一个基于代码这里的示例。我编辑了
INNER_RADIUS
、START_ANGLE
、END_ANGLE
和STEP_ANGLE
。我还添加了一个新变量,GAP
。 GAP
是每个段之间的空间。
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.ArcTo;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
public class App extends Application {
private static final double OUTER_RADIUS =300, INNER_RADIUS = 140, ORIGIN_X = 300, ORIGIN_Y = 300;
private static final double START_ANGLE =0, END_ANGLE = 360, STEP_ANGLE = 36;
private static final double GAP = .5;
@Override
public void start(Stage primaryStage) {
Group group = new Group();
for(double angle = START_ANGLE; angle < END_ANGLE ; angle += STEP_ANGLE ){
Point2D innerArcStart = getPoint(INNER_RADIUS, angle + GAP);
Point2D innerArcEnd = getPoint(INNER_RADIUS, angle - GAP + STEP_ANGLE);
Point2D outerArcStart = getPoint(OUTER_RADIUS, angle + GAP);
Point2D outerArcEnd = getPoint(OUTER_RADIUS, angle - GAP + STEP_ANGLE);
var path = getPath(innerArcStart, innerArcEnd, outerArcStart, outerArcEnd);
path.setOnMouseEntered((mouseEnteredEvent) -> {
path.setScaleX(1.2);
path.setScaleY(1.2);
});
path.setOnMouseExited((mouseExitedEvent) -> {
path.setScaleX(1);
path.setScaleY(1);
});
group.getChildren().add(path);
}
primaryStage.setScene(new Scene(new Pane(group)));
primaryStage.show();
}
private Point2D getPoint(double radius, double angle){
double x = ORIGIN_X - radius * Math.cos(Math.toRadians(angle));
double y = ORIGIN_Y - radius * Math.sin(Math.toRadians(angle));
return new Point2D(x, y);
}
private Shape getPath(Point2D innerArcStart, Point2D innerArcEnd, Point2D outerArcStart, Point2D outerArcEnd){
var path = new Path(
new MoveTo(innerArcStart.getX(), innerArcStart.getY()),
new LineTo(outerArcStart.getX(), outerArcStart.getY()), //left line
new ArcTo(OUTER_RADIUS, OUTER_RADIUS, 0, outerArcEnd.getX(), outerArcEnd.getY(), false, true), //outer arc
new LineTo(innerArcEnd.getX(),innerArcEnd.getY()), //right line
new ArcTo(INNER_RADIUS, INNER_RADIUS, 0, innerArcStart.getX(), innerArcStart.getY(), false, false)
);
path.setFill(Color.color(Math.random(), Math.random(), Math.random()));
return path;
}
public static void main(String args[]){
launch(args);
}
}
输出