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

时间:2015-04-01 15:18:01

标签: javafx mouseevent

我希望用户能够拖动窗格周围的圆圈。圈子似乎没有注册(几乎)没有鼠标事件(最终定义)。我有一个空窗格的相同的确切代码,它工作得很好。如果我改变

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

1 个答案:

答案 0 :(得分:1)

即使您已经发布了一个示例,我也希望向您展示一般的方式。有几种方法,这是有效的方法:

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。在这种情况下,点击事件不会被注册。您应该使用Color.TRANSPARENT。您可以使用上述方法验证事件差异。