JavaFX Circle对象未正确注册鼠标事件



我希望用户能够围绕窗格拖动和移动圆圈。圆圈似乎没有记录(几乎)鼠标事件(正如最后定义的那样)。我有一个空窗格的完全相同的代码,它工作得很好。如果我更改

circle1.setOnMouseDragged

paneForCircles.setOnMouseDragged

它工作得很好,但不是我想要的,因为我需要操纵两个圆圈。有什么想法吗?如果你也能告诉我,如果圆的中心离窗格边界太近,如何隐藏与相邻元素重叠的部分,我将不胜感激。

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle; 
import javafx.stage.Stage;

public class Ex168 extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
    Circle circle1 = new Circle(30);
    Circle circle2 = new Circle(35);
    circle1.setCenterX(100);
    circle1.setCenterY(100);
    circle2.setCenterX(150);
    circle2.setCenterY(120);
    circle1.setStroke(Color.BLACK);
    circle1.setFill(null);
    circle2.setStroke(Color.BLACK);
    circle2.setFill(null);
    VBox vBoxForScene = new VBox(5);
    vBoxForScene.setPadding(new Insets(5));
    vBoxForScene.setAlignment(Pos.TOP_CENTER);
    Pane paneForCircles = new Pane();
    paneForCircles.setStyle("-fx-border-color: black");
    vBoxForScene.heightProperty().addListener(ov -> paneForCircles.setPrefHeight(vBoxForScene.heightProperty().divide(1.2).doubleValue()));
    paneForCircles.setPrefHeight(300);
    HBox hBoxForFields = new HBox(5);
    hBoxForFields.setAlignment(Pos.CENTER);
    hBoxForFields.setSpacing(5);
    // VBofForLeftFields
    VBox vBoxForLeftFields = new VBox(5);
    vBoxForLeftFields.setAlignment(Pos.CENTER_LEFT);
    Label lblCircle1 = new Label("Enter Circle 1 info");
    lblCircle1.setAlignment(Pos.TOP_LEFT);
    TextField tfCircle1CenterX = new TextField();
    tfCircle1CenterX.textProperty().bind(circle1.centerXProperty().asString());
    TextField tfCircle1CenterY = new TextField();
    tfCircle1CenterY.textProperty().bind(circle1.centerYProperty().asString());
    TextField tfCircle1Radius = new TextField();
    tfCircle1Radius.textProperty().bind(circle1.radiusProperty().asString());
    tfCircle1CenterX.setPrefColumnCount(5);
    tfCircle1Radius.setPrefColumnCount(5);
    tfCircle1CenterY.setPrefColumnCount(5);
    Label lblCenterX = new Label("Center x:", tfCircle1CenterX);
    Label lblCenterY = new Label("Center x:", tfCircle1CenterY);
    Label lblCircle1Radius= new Label("Radius:   ", tfCircle1Radius);
    lblCenterX.setContentDisplay(ContentDisplay.RIGHT);
    lblCenterY.setContentDisplay(ContentDisplay.RIGHT);
    lblCircle1Radius.setContentDisplay(ContentDisplay.RIGHT);
    //VBoxForRightFields
    VBox vBoxForRightFields = new VBox(5);
    Label lblCircle2 = new Label("Enter Circle 2 info");
    TextField tfCircle2CenterX = new TextField();
    TextField tfCircle2CenterY = new TextField();
    TextField tfCircle2Radius = new TextField();
    tfCircle2CenterX.setPrefColumnCount(5);
    tfCircle2CenterX.textProperty().bind(circle2.centerXProperty().asString());
    tfCircle2Radius.setPrefColumnCount(5);
    tfCircle2Radius.textProperty().bind(circle2.radiusProperty().asString());
    tfCircle2CenterY.setPrefColumnCount(5);
    tfCircle2CenterY.textProperty().bind(circle2.centerYProperty().asString());
    Label lblCenter2X = new Label("Center x:", tfCircle2CenterX);
    Label lblCenter2Y = new Label("Center x:", tfCircle2CenterY);
    Label lblCircle2Radius= new Label("Radius:   ", tfCircle2Radius);
    lblCenter2X.setContentDisplay(ContentDisplay.RIGHT);
    lblCenter2Y.setContentDisplay(ContentDisplay.RIGHT);
    lblCircle2Radius.setContentDisplay(ContentDisplay.RIGHT);
    vBoxForRightFields.getChildren().addAll(lblCircle2, lblCenter2X, lblCenter2Y, lblCircle2Radius);
    vBoxForLeftFields.getChildren().addAll(lblCircle1, lblCenterX, lblCenterY, lblCircle1Radius);
    hBoxForFields.getChildren().addAll(vBoxForLeftFields, vBoxForRightFields);
    Label lblResult = new Label("Do the two circles intersect?");
    Button btReDrawCircles = new Button("Redraw Circles");
    vBoxForScene.getChildren().addAll(lblResult, paneForCircles, hBoxForFields, btReDrawCircles);
    circle1.setOnMouseDragged(e -> {
        System.out.println(e.getX());
        circle1.setCenterX(e.getX());
        circle1.setCenterY(e.getY());
    });
    circle2.setOnMouseDragged(e -> {
        circle2.setCenterX(e.getX());
        circle2.setCenterY(e.getY());
    });
    paneForCircles.getChildren().addAll(circle1, circle2);
    Scene scene = new Scene(vBoxForScene);
    primaryStage.setScene(scene);
    primaryStage.setMinHeight(400);
    primaryStage.setMinWidth(340);
    primaryStage.setAlwaysOnTop(true);
    primaryStage.show();
    circle1.requestFocus();
}

}

另一方面,这个代码应该做同样的事情,它完美地工作

public class CircleDraggingSample extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
    final double RADIUS=10;
    Pane pane = new Pane();
    pane.setPrefHeight(300);
    pane.setPrefWidth(300);
    Circle circle1 = new Circle(RADIUS);
    circle1.setCenterX(30);
    circle1.setCenterY(30);
    Circle circle2 = new Circle(RADIUS);
    circle2.setCenterX(100);
    circle2.setCenterY(100);
    Line line = new Line();
    line.endXProperty().bind(circle2.centerXProperty());
    line.endYProperty().bind(circle2.centerYProperty());
    line.startXProperty().bind(circle1.centerXProperty());
    line.startYProperty().bind(circle1.centerYProperty());
    pane.getChildren().addAll(circle1, circle2, line);
    circle2.setOnMouseDragged(e -> {
        circle2.setCenterX(e.getX());
        circle2.setCenterY(e.getY());
    });
    circle1.setOnMouseDragged(e -> {
        circle1.setCenterX(e.getX());
        circle1.setCenterY(e.getY());
    });
    Scene scene = new Scene(pane);
    primaryStage.setScene(scene);
    primaryStage.show();
}
}

尽管您已经发布了一个示例,但我更愿意向您展示我的示例是如何实现的。有几种方法,这是一种有效的方法:

public class DragNodes extends Application {
    public static List<Circle> circles = new ArrayList<Circle>();
    public static void main(String[] args) {
        launch(args);
    }
    @Override
    public void start(Stage primaryStage) {
        Group root = new Group();
        Circle circle1 = new Circle( 100, 100, 50);
        circle1.setStroke(Color.GREEN);
        circle1.setFill(Color.GREEN.deriveColor(1, 1, 1, 0.3));
        Circle circle2 = new Circle( 200, 200, 50);
        circle2.setStroke(Color.BLUE);
        circle2.setFill(Color.BLUE.deriveColor(1, 1, 1, 0.3));
        Line line = new Line();
        line.setStrokeWidth(20);
        // binding
        line.startXProperty().bind(circle1.centerXProperty());
        line.startYProperty().bind(circle1.centerYProperty());
        line.endXProperty().bind(circle2.centerXProperty());
        line.endYProperty().bind(circle2.centerYProperty());
        MouseGestures mg = new MouseGestures();
        mg.makeDraggable( circle1);
        mg.makeDraggable( circle2);
        mg.makeDraggable( line);
        root.getChildren().addAll(circle1, circle2, line);
        primaryStage.setScene(new Scene(root, 1024, 768));
        primaryStage.show();
    }

    public static class MouseGestures {
        class DragContext {
            double x;
            double y;
        }
        DragContext dragContext = new DragContext();
        public void makeDraggable( Node node) {
            node.setOnMousePressed( onMousePressedEventHandler);
            node.setOnMouseDragged( onMouseDraggedEventHandler);
            node.setOnMouseReleased(onMouseReleasedEventHandler);
        }
        EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                if( event.getSource() instanceof Circle) {
                    Circle circle = ((Circle) (event.getSource()));
                    dragContext.x = circle.getCenterX() - event.getSceneX();
                    dragContext.y = circle.getCenterY() - event.getSceneY();
                } else {
                    Node node = ((Node) (event.getSource()));
                    dragContext.x = node.getTranslateX() - event.getSceneX();
                    dragContext.y = node.getTranslateY() - event.getSceneY();
                }
            }
        };
        EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                if( event.getSource() instanceof Circle) {
                    Circle circle = ((Circle) (event.getSource()));
                    circle.setCenterX( dragContext.x + event.getSceneX());
                    circle.setCenterY( dragContext.y + event.getSceneY());
                } else {
                    Node node = ((Node) (event.getSource()));
                    node.setTranslateX( dragContext.x + event.getSceneX());
                    node.setTranslateY( dragContext.y + event.getSceneY());
                }
            }
        };
        EventHandler<MouseEvent> onMouseReleasedEventHandler = new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
            }
        };
    }
}

它展示了如何拖动圆并绑定另一个节点(线),以便在拖动圆时也可以对其进行修改。也可以单独拖动线,该线是一个节点,处理方式不同。

如果你还有问题,请告诉我。


一般来说,最好将其添加到节点中,以便了解发生了哪些事件:

 node.addEventFilter(Event.ANY, e -> System.out.println( e));

然后在屏幕上执行某些操作时检查控制台输出。


关于您的主要问题:不能将Fill设置为null。在这种情况下,单击事件将不会被注册。您应该使用"颜色"。取而代之的是透明。您可以使用上述方法验证事件差异。

最新更新