Java FX嵌套事件处理程序我想在调用子处理程序时阻止父处理程序

时间:2018-11-07 18:48:38

标签: javafx

我有一个fxml鼠标事件处理程序方法,每次单击窗格时,屏幕上都会弹出一个对话框,要求您提供信息。在对话框上单击“确定”后,带有文本的圆圈将添加到堆栈窗格中,然后将堆栈窗格添加到用户单击的窗格中。

但是,我试图实现一个事件处理程序,在该事件处理程序中,可以通过使用鼠标拖动堆栈窗格来移动堆栈窗格。我的事件处理程序可以工作,但是每当我完成拖动堆栈窗格时,都会弹出一个对话框。我不希望在移动圆时弹出对话框,我该如何更改代码以实现阻止弹出处理程序的方法?

谢谢。

我的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 :(得分:1)

要阻止Event传播,请使用Event.consume()

  

将此Event标记为已使用。这将阻止其进一步传播。

根据您的描述,看来handleAddVertexMOUSE_CLICKED处理程序。您必须向使用EventHandler事件的新创建的StackPane添加另一个MOUSE_CLICKED

stack.setOnMouseClicked(Event::consume);

这将阻止MOUSE_CLICKED事件冒泡到具有Node处理程序的handleAddVertex


有关JavaFX中事件处理的更多信息,请参见JavaFX: Handling Events


这是一个小示例,您可以看到使用事件与不使用事件之间的区别:

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

}