код javafx для выбора только границы ar c для события MOUSE_CLICKED - PullRequest
4 голосов
/ 26 апреля 2020

Я хочу иметь возможность щелкать только по границе Arc s, перекрывающих друг друга в StackPane. В настоящее время мой код ниже также выбирает заполнение Arc s, и я не могу запустить событие MOUSE_CLICKED для arc1, когда я нажимаю точку p3 в изображении ниже. Объяснение моего желаемого результата и текущего результата также приведено ниже.

enter image description here

  • Когда пользователь нажимает p1, код работает как задумано, печатает «arc2» "
  • Когда пользователь нажимает p2, код печатает" arc2 ", в то время как предполагаемая операция ничего не делает
  • Когда пользователь нажимает p3, код печатает" arc2 ", тогда как предполагаемая операция заключается в печати" 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 я реализовал свое предполагаемое поведение следующим образом:

    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);
      }
    }

Тем не менее, вопрос все еще остается технически без ответа, так как первоначальный вопрос требует либо;

  • Способ исключения области «заливки» из событий щелчка, или,
  • Способ получения обработчиков событий всех фигур, содержащих точку щелчка, которая запускается, когда содержится точка щелчка в пределах более чем одной формы

1 Ответ

3 голосов
/ 26 апреля 2020

Просто проверьте, содержит ли Узел нажатую точку:

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);
    }
}


Редактировать: Чтобы избежать событий щелчка мышью из области заполнения области c (желтая область на изображении)

enter image description here

Вы можете построить только форму контура без области заливки. Давайте назовем ar c на изображении arc1. Создайте второй ar c, 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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...