我有一个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);
}
}
答案 0 :(得分:1)
要阻止Event
传播,请使用Event.consume()
。
将此
Event
标记为已使用。这将阻止其进一步传播。
根据您的描述,看来handleAddVertex
是MOUSE_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();
}
}
}