Java FX вложенный обработчик событий. Я хочу заблокировать родительский обработчик, когда вызывается дочерний обработчик - PullRequest
0 голосов
/ 07 ноября 2018

У меня есть метод обработчика событий мыши fxml, при котором каждый раз, когда я нажимаю на панель, на экране появляется всплывающее диалоговое окно с запросом информации. Когда в диалоговом окне нажата кнопка «ОК», на панель стека добавляется круг с текстом, а затем панель стека добавляется на панель, на которой щелкнул пользователь.

Однако я пытаюсь реализовать обработчик событий, в котором я могу перемещать панель стека, перетаскивая панель стека с помощью мыши. Мой обработчик событий работает, но каждый раз, когда я заканчиваю перетаскивать панель стека, появляется всплывающее диалоговое окно. Я не хочу, чтобы всплывающее диалоговое окно появлялось при перемещении круга. Как бы я изменил свой код, чтобы сделать это? Есть ли способ блокировки обработчика всплывающих окон?

Спасибо.

Метод My Handler:

    @FXML
    private void handleAddVertex(MouseEvent event) {

        boolean okClicked = main.showAddVertexPopUp(this);

        if(okClicked) {

            String vertexText = "";

            if(getSelectedDataChoice().equals("Integer")) {

                vertexText = dataModel.getListOfIntVertices().get(dataModel.getListOfIntVertices().size() - 1).toString();

            }else if(getSelectedDataChoice().equals("Double")){

                vertexText = dataModel.getListOfDoubleVertices().get(dataModel.getListOfDoubleVertices().size() - 1).toString();

            }else {

                vertexText = dataModel.getListOfStringVertices().get(dataModel.getListOfStringVertices().size() - 1).toString();

            }

            EventHandler<MouseEvent> circleOnMousePressedEventHandler = 
                    new EventHandler<MouseEvent>() {

                    @Override
                    public void handle(MouseEvent t) {
                        orgSceneX = t.getSceneX();
                        orgSceneY = t.getSceneY();
                        orgTranslateX = ((StackPane)(t.getSource())).getTranslateX();
                        orgTranslateY = ((StackPane)(t.getSource())).getTranslateY();
                    }
                };

                EventHandler<MouseEvent> circleOnMouseDraggedEventHandler = 
                    new EventHandler<MouseEvent>() {

                    @Override
                    public void handle(MouseEvent t) {
                        double offsetX = t.getSceneX() - orgSceneX;
                        double offsetY = t.getSceneY() - orgSceneY;
                        double newTranslateX = orgTranslateX + offsetX;
                        double newTranslateY = orgTranslateY + offsetY;

                        ((StackPane)(t.getSource())).setTranslateX(newTranslateX);
                        ((StackPane)(t.getSource())).setTranslateY(newTranslateY);
                    }
                };

            double x = event.getX();
            double y = event.getY();

            Circle vertex = new Circle(x, y, 20, Color.WHITE);
            vertex.setStroke(Color.BLACK);

            Text text = new Text (vertexText);

            StackPane stack = new StackPane();

            stack.getChildren().addAll(vertex, text);
            stack.setLayoutX(x);
            stack.setLayoutY(y);

            stack.setOnMousePressed(circleOnMousePressedEventHandler);
            stack.setOnMouseDragged(circleOnMouseDraggedEventHandler);

            centerPane.getChildren().add(stack);

        }   


    }

1 Ответ

0 голосов
/ 07 ноября 2018

Чтобы остановить распространение Event, вы используете Event.consume().

Отмечает это Event как использованное. Это останавливает его дальнейшее распространение.

Из вашего описания, похоже, handleAddVertex - обработчик MOUSE_CLICKED. Вам нужно будет добавить еще один EventHandler к недавно созданному StackPane, который потребляет MOUSE_CLICKED событий.

stack.setOnMouseClicked(Event::consume);

Это предотвратит всплытие события MOUSE_CLICKED до Node с обработчиком handleAddVertex.


Для получения дополнительной информации об обработке событий в JavaFX см. JavaFX: Обработка событий .


Вот небольшой пример, где вы можете увидеть разницу между потреблением и не поглощением события:

import java.util.function.Predicate;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ButtonType;
import javafx.scene.control.CheckBox;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class Main extends Application {

  private CheckBox consumeClickEventsCheckBox;

  @Override
  public void start(Stage primaryStage) throws Exception {
    consumeClickEventsCheckBox = new CheckBox("Consume click events");
    consumeClickEventsCheckBox.setSelected(true);

    HBox top = new HBox(consumeClickEventsCheckBox);
    top.setPadding(new Insets(10));
    top.setAlignment(Pos.CENTER);

    Pane center = new Pane();
    center.setBorder(new Border(new BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, null, null)));
    center.setOnMouseClicked(this::handleAddCircle);

    Rectangle clip = new Rectangle();
    clip.widthProperty().bind(center.widthProperty());
    clip.heightProperty().bind(center.heightProperty());
    center.setClip(clip);

    BorderPane root = new BorderPane(center);
    root.setTop(top);

    Scene scene = new Scene(root, 600, 400);
    primaryStage.setScene(scene);
    primaryStage.show();
  }

  private void handleAddCircle(MouseEvent event) {
    event.consume();

    Alert confirm = new Alert(AlertType.CONFIRMATION);
    confirm.initOwner(((Node) event.getSource()).getScene().getWindow());
    confirm.setHeaderText(null);
    confirm.setContentText("Do you want to add a circle here?");

    if (confirm.showAndWait().filter(Predicate.isEqual(ButtonType.OK)).isPresent()) {
      Circle circle = new Circle(event.getX(), event.getY(), 25);
      circle.setOnMousePressed(this::handleCirclePressed);
      circle.setOnMouseDragged(this::handleCircleDragged);
      circle.setOnMouseClicked(this::handleCircleClicked);

      ((Pane) event.getSource()).getChildren().add(circle);
    }
  }

  private Point2D origin;

  private void handleCirclePressed(MouseEvent event) {
    event.consume();
    origin = new Point2D(event.getX(), event.getY());
  }

  private void handleCircleDragged(MouseEvent event) {
    event.consume();
    Circle circle = (Circle) event.getSource();
    circle.setTranslateX(circle.getTranslateX() + event.getX() - origin.getX());
    circle.setTranslateY(circle.getTranslateY() + event.getY() - origin.getY());
  }

  /*
   * Will consume the MOUSE_CLICKED event only if the CheckBox is selected. You can test
   * the behavior of consuming the event by toggling the CheckBox.
   */
  private void handleCircleClicked(MouseEvent event) {
    if (consumeClickEventsCheckBox.isSelected()) {
      event.consume();
    }
  }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...