我只希望单击Arc
中彼此重叠的StackPane
的边界。当前,我的下面代码也选择了Arc
的填充,并且当我单击下图中的点p3时,无法启动MOUSE_CLICKED
的arc1
事件。我期望的结果和当前结果的解释也在下面。
这是因为即使填充是透明的并且
Arc2
设置为Arc1
,PickOnBounds
的填充区域还是在false
之前拾取的。我正在尝试找到一种方法来使填充区域不被拾取。失败的话,我想触发两个Arc
的事件处理程序,以便我自己处理行为。代表我的问题的代码:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.stage.Stage;
public class Example extends Application {
@Override
public void start(Stage primaryStage) {
Arc arc1 = new Arc(100, 100, 100, 100, 90, 90);
Arc arc2 = new Arc(0, 100, 100, 100, 0, 90);
arc1.setStroke(Color.BLACK);
arc2.setStroke(Color.BLACK);
arc1.setFill(Color.TRANSPARENT);
arc2.setFill(Color.TRANSPARENT);
arc1.setStrokeWidth(10);
arc2.setStrokeWidth(10);
arc1.setType(ArcType.OPEN);
arc2.setType(ArcType.OPEN);
arc1.setPickOnBounds(false);
arc2.setPickOnBounds(false);
arc1.setOnMouseClicked(event -> System.out.println("arc1"));
arc2.setOnMouseClicked(event -> System.out.println("arc2"));
StackPane root = new StackPane();
root.getChildren().add(arc1);
root.getChildren().add(arc2);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Picking Issues");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
编辑:
在c0der's的帮助下,我实现了预期的行为,如下所示:
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.stage.Stage;
public class Example extends Application {
private Arc arc1, arc2;
private StackPane root;
@Override
public void start(Stage primaryStage) {
arc1 = getArc(200, 200, 200, 200, 90, 90, "arc1");
arc2 = getArc(0, 200, 200, 200, 0, 90, "arc2");
root = new StackPane(arc1, arc2);
root.setOnMouseClicked(event -> onStackPaneClick(event.getX(), event.getY()));
Scene scene = new Scene(root, 200, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
private Arc getArc(double x, double y, double radiusX, double radiusY, double startAngle, double endAngle, String userData){
Arc arc = new Arc(x,y, radiusX,radiusY,startAngle, endAngle);
arc.setStroke(Color.BLACK);
arc.setFill(Color.TRANSPARENT);
arc.setStrokeWidth(10);
arc.setType(ArcType.OPEN);
arc.setPickOnBounds(false);
arc.setUserData(userData);
return arc;
}
private void onStackPaneClick(double x, double y) {
for (Node itNode : root.getChildren()) {
if (itNode.contains(new Point2D(x, y))) {
if (itNode instanceof Arc) {
Arc itArc = (Arc) itNode;
double centerDistance = Math.sqrt(
(x - itArc.getCenterX()) * (x - itArc.getCenterX()) +
(y - itArc.getCenterY()) * (y - itArc.getCenterY()));
if (centerDistance >= itArc.getRadiusX() - itArc.getStrokeWidth() / 2) {
System.out.println(itArc.getUserData());
break;
}
}
}
}
}
public static void main(String[] args) {
launch(args);
}
}
但是,由于最初的问题需要,该问题在技术上仍然没有答案。
最佳答案
只需检查Node contains是否为点击点:
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.stage.Stage;
public class FxmlTest extends Application {
private Arc arc1, arc2;
@Override
public void start(Stage primaryStage) {
arc1 = getArc(100, 100, 100, 100, 90, 90);
arc2 = getArc(0, 100, 100, 100, 0, 90);
StackPane root = new StackPane(arc1, arc2);
Scene scene = new Scene(root, 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
private Arc getArc(double x, double y, double radiusX, double radiusY, double startAngle, double endAngle){
Arc arc = new Arc(x,y, radiusX,radiusY,startAngle, endAngle);
arc.setStroke(Color.BLACK);
arc.setFill(Color.TRANSPARENT);
arc.setStrokeWidth(10);
arc.setType(ArcType.OPEN);
arc.setPickOnBounds(false);
arc.setOnMouseClicked(event -> checkClickedPoint(event.getX(), event.getY()));
return arc;
}
private void checkClickedPoint(double x, double y) {
Point2D clickedPoint = new Point2D(x, y);
if(arc1.contains(clickedPoint)) {System.out.println("arc1");}
if(arc2.contains(clickedPoint)) {System.out.println("arc2");}
}
public static void main(String[] args) {
launch(null);
}
}
编辑:
为避免弧形填充区域(图像中的黄色区域)发生鼠标单击事件
您只能构建轮廓的形状,而无需填充区域。
我们将其称为
arc1
中的弧。构造第二个弧,
arc2
,它较小并包含在arc1
中。arc2
的构造使其覆盖黄色区域。从
arc2
减去arc1
会返回一个形状,该形状是arc1
的轮廓:class ArcContour {
private final Shape arcContour;
private static final double STROKE = 10;
public ArcContour(double x, double y, double radiusX, double radiusY, double startAngle, double length) {
Arc arc1 = new Arc(x,y, radiusX,radiusY,startAngle, length);
arc1.setStroke(Color.BLACK);
arc1.setStrokeWidth(STROKE);
arc1.setStrokeType(StrokeType.INSIDE);
arc1.setType(ArcType.OPEN);
arc1.setPickOnBounds(false);
Arc arc2 = new Arc(x,y, radiusX - STROKE,radiusY - STROKE,startAngle, length);
arc2.setStrokeType(StrokeType.INSIDE);
arcContour = Shape.subtract(arc1, arc2);
}
Shape getShape() {
return arcContour;
}
}
通过以下方式进行测试:
public class FxmlTest extends Application {
private Shape shape;
private static final double RADIUS = 100;
@Override
public void start(Stage primaryStage) {
shape = new ArcContour(150, 150, RADIUS, RADIUS, 30, 150).getShape();
shape.setOnMouseClicked(event -> checkClickedPoint(event.getX(), event.getY()));
StackPane root = new StackPane(shape);
Scene scene = new Scene(root, 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
//this functinality can be refactored to ArcContour
private void checkClickedPoint(double x, double y) {
if( shape.contains(new Point2D(x, y))) {System.out.println("Arc clicked");}
}
public static void main(String[] args) {
launch(null);
}
}